fixes #155 replace Quartz 2 integration with Quartz 3 integration
This commit is contained in:
@@ -65,16 +65,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Testing.Microsoft.Te
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Messaging.Ems", "src\Spring\Spring.Messaging.Ems\Spring.Messaging.Ems.csproj", "{900E3839-301E-48B1-BAEB-B6645620ACFF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Scheduling.Quartz2", "src\Spring\Spring.Scheduling.Quartz2\Spring.Scheduling.Quartz2.csproj", "{E823D54C-CE82-4868-929F-5F95A999F123}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Scheduling.Quartz3", "src\Spring\Spring.Scheduling.Quartz3\Spring.Scheduling.Quartz3.csproj", "{E823D54C-CE82-4868-929F-5F95A999F123}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Scheduling.Quartz2.Tests", "test\Spring\Spring.Scheduling.Quartz2.Tests\Spring.Scheduling.Quartz2.Tests.csproj", "{247787CF-ECE1-4675-8B42-7DF4329A4891}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Scheduling.Quartz3.Integration.Tests", "test\Spring\Spring.Scheduling.Quartz3.Integration.Tests\Spring.Scheduling.Quartz3.Integration.Tests.csproj", "{8CF0F34A-CC93-4D87-AE14-A2DEEF072F26}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Scheduling.Quartz3.Tests", "test\Spring\Spring.Scheduling.Quartz3.Tests\Spring.Scheduling.Quartz3.Tests.csproj", "{247787CF-ECE1-4675-8B42-7DF4329A4891}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Messaging.Ems.Integration.Tests", "test\Spring\Spring.Messaging.Ems.Integration.Tests\Spring.Messaging.Ems.Integration.Tests.csproj", "{FA934E92-C8C2-428A-BE2A-26818F17A787}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Messaging.Nms.Integration.Tests", "test\Spring\Spring.Messaging.Nms.Integration.Tests\Spring.Messaging.Nms.Integration.Tests.csproj", "{E5323AC8-137E-4EF7-BC62-3BD6FC0576CD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Scheduling.Quartz2.Integration.Tests", "test\Spring\Spring.Scheduling.Quartz2.Integration.Tests\Spring.Scheduling.Quartz2.Integration.Tests.csproj", "{8CF0F34A-CC93-4D87-AE14-A2DEEF072F26}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Web.Conversation.NHibernate5", "src\Spring\Spring.Web.Conversation.NHibernate5\Spring.Web.Conversation.NHibernate5.csproj", "{CF375928-B6D5-485C-B04D-2BC41D9DBF1E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring.Web.Conversation.NHibernate5.Tests", "test\Spring\Spring.Web.Conversation.NHibernate5.Tests\Spring.Web.Conversation.NHibernate5.Tests.csproj", "{C57B05EA-FD1A-40EC-BB60-D2E45AB1A86A}"
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderRegionName/@EntryValue">License</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
@@ -15,6 +19,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
|
||||
11
Spring.build
11
Spring.build
@@ -417,6 +417,7 @@ Commandline Examples:
|
||||
<include name="${spring.basedir}/test/Spring/Spring.Testing.NUnit.Tests/Spring.Testing.NUnit.Tests.csproj" />
|
||||
<include name="${spring.basedir}/test/Spring/Spring.Data.NHibernate5.Integration.Tests/Spring.Data.NHibernate5.Integration.Tests.csproj" />
|
||||
<include name="${spring.basedir}/test/Spring/Spring.Data.NHibernate5.Tests/Spring.Data.NHibernate5.Tests.csproj" />
|
||||
<include name="${spring.basedir}/test/Spring/Spring.Scheduling.Quartz3.Tests/Spring.Scheduling.Quartz3.Tests.csproj" />
|
||||
</items>
|
||||
</in>
|
||||
<do>
|
||||
@@ -1071,9 +1072,9 @@ Commandline Examples:
|
||||
<include name="*/*/Spring.Messaging.xml"/>
|
||||
<include name="*/*/Spring.Messaging.pdb"/>
|
||||
|
||||
<include name="*/*/Spring.Scheduling.Quartz2.dll"/>
|
||||
<include name="*/*/Spring.Scheduling.Quartz2.xml"/>
|
||||
<include name="*/*/Spring.Scheduling.Quartz2.pdb"/>
|
||||
<include name="*/*/Spring.Scheduling.Quartz3.dll"/>
|
||||
<include name="*/*/Spring.Scheduling.Quartz3.xml"/>
|
||||
<include name="*/*/Spring.Scheduling.Quartz3.pdb"/>
|
||||
|
||||
<include name="*/*/Spring.Template.Velocity.dll"/>
|
||||
<include name="*/*/Spring.Template.Velocity.xml"/>
|
||||
@@ -1277,7 +1278,7 @@ Commandline Examples:
|
||||
<include name="src/Spring/Spring.Messaging/**"/>
|
||||
<include name="src/Spring/Spring.Messaging.Nms/**"/>
|
||||
<include name="src/Spring/Spring.Messaging.Ems/**"/>
|
||||
<include name="src/Spring/Spring.Scheduling.Quartz2/**"/>
|
||||
<include name="src/Spring/Spring.Scheduling.Quartz3/**"/>
|
||||
<include name="src/Spring/Spring.Template.Velocity/**"/>
|
||||
<include name="src/Spring/Spring.Testing.NUnit/**"/>
|
||||
<include name="src/Spring/Spring.Testing.Microsoft/**"/>
|
||||
@@ -1298,7 +1299,7 @@ Commandline Examples:
|
||||
<include name="test/Spring/Spring.Messaging.Nms.Tests/**"/>
|
||||
<include name="test/Spring/Spring.Messaging.Nms.Integration.Tests/**"/>
|
||||
<include name="test/Spring/Spring.Messaging.Ems.Tests/**"/>
|
||||
<include name="test/Spring/Spring.Scheduling.Quartz2.Tests/**"/>
|
||||
<include name="test/Spring/Spring.Scheduling.Quartz3.Tests/**"/>
|
||||
<include name="test/Spring/Spring.Template.Velocity.Tests/**"/>
|
||||
<include name="test/Spring/Spring.Testing.NUnit.Tests/**"/>
|
||||
<include name="test/Spring/Spring.Testing.Microsoft.Tests/**"/>
|
||||
|
||||
@@ -10,6 +10,7 @@ Release Notes - Spring.NET - Version 3.0.0
|
||||
Breaking Changes
|
||||
|
||||
* .NET 4.5.2 is the lowest full framework supported
|
||||
* Tranasaction definitions no longer have EnterpriseServicesInteropOption, it was replaced by TransactionScopeAsyncFlowOption
|
||||
|
||||
New Feature Highlights
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<project name="Spring.Scheduling.Quartz.Example" default="build" xmlns="http://nant.sf.net/schemas/nant.xsd">
|
||||
|
||||
<target name="build">
|
||||
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -5,6 +5,14 @@ VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Scheduling.Quartz.Example.2010", "src\Spring.Scheduling.Quartz.Example.csproj", "{0C0D8C65-90DE-4914-9940-4C684C54971B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Scheduling.Quartz3", "..\..\..\src\Spring\Spring.Scheduling.Quartz3\Spring.Scheduling.Quartz3.csproj", "{E397E260-643A-4929-8979-3483BF0C77CB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Core", "..\..\..\src\Spring\Spring.Core\Spring.Core.csproj", "{7BF79668-CD22-461B-BF82-5571E3E1119E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Data", "..\..\..\src\Spring\Spring.Data\Spring.Data.csproj", "{7FBD7BF1-B978-4DBC-BDBC-B8B20865E96D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Aop", "..\..\..\src\Spring\Spring.Aop\Spring.Aop.csproj", "{6905DB1E-B4B7-4B5A-9E6F-72881BB6C98D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -15,6 +23,22 @@ Global
|
||||
{0C0D8C65-90DE-4914-9940-4C684C54971B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0C0D8C65-90DE-4914-9940-4C684C54971B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0C0D8C65-90DE-4914-9940-4C684C54971B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E397E260-643A-4929-8979-3483BF0C77CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E397E260-643A-4929-8979-3483BF0C77CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E397E260-643A-4929-8979-3483BF0C77CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E397E260-643A-4929-8979-3483BF0C77CB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7BF79668-CD22-461B-BF82-5571E3E1119E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7BF79668-CD22-461B-BF82-5571E3E1119E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7BF79668-CD22-461B-BF82-5571E3E1119E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7BF79668-CD22-461B-BF82-5571E3E1119E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7FBD7BF1-B978-4DBC-BDBC-B8B20865E96D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7FBD7BF1-B978-4DBC-BDBC-B8B20865E96D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7FBD7BF1-B978-4DBC-BDBC-B8B20865E96D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7FBD7BF1-B978-4DBC-BDBC-B8B20865E96D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6905DB1E-B4B7-4B5A-9E6F-72881BB6C98D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6905DB1E-B4B7-4B5A-9E6F-72881BB6C98D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6905DB1E-B4B7-4B5A-9E6F-72881BB6C98D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6905DB1E-B4B7-4B5A-9E6F-72881BB6C98D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,34 +1,31 @@
|
||||
using System;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Quartz;
|
||||
|
||||
namespace Spring.Scheduling.Quartz.Example
|
||||
{
|
||||
/// <summary>
|
||||
/// Example job.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Example job.
|
||||
/// </summary>
|
||||
public class ExampleJob : QuartzJobObject
|
||||
{
|
||||
|
||||
private string userName;
|
||||
|
||||
/// <summary>
|
||||
/// Simple property that can be injected.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Simple property that can be injected.
|
||||
/// </summary>
|
||||
public string UserName
|
||||
{
|
||||
set { userName = value; }
|
||||
set => userName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
protected override void ExecuteInternal(IJobExecutionContext context)
|
||||
/// <inheritdoc />
|
||||
protected override Task ExecuteInternal(IJobExecutionContext context)
|
||||
{
|
||||
Console.WriteLine("{0}: ExecuteInternal called, user name: {1}, next fire time {2}",
|
||||
DateTime.Now, userName, context.NextFireTimeUtc.Value.ToLocalTime());
|
||||
}
|
||||
Console.WriteLine(
|
||||
$"{DateTime.Now}: ExecuteInternal called, user name: {userName}, next fire time {context.NextFireTimeUtc?.ToLocalTime()}");
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,13 @@
|
||||
<TargetFramework>net452</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Spring.Core">
|
||||
<HintPath>..\..\..\..\build\$(Configuration)\Spring.Core\$(TargetFramework)\Spring.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Spring.Scheduling.Quartz2">
|
||||
<HintPath>..\..\..\..\build\$(Configuration)\Spring.Scheduling.Quartz2\$(TargetFramework)\Spring.Scheduling.Quartz2.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="spring-objects.xml" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Common.Logging" Version="$(CommonLoggingVersion)" />
|
||||
<PackageReference Include="Quartz" Version="2.6.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Spring\Spring.Scheduling.Quartz3\Spring.Scheduling.Quartz3.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
|
||||
|
||||
<object name="exampleJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz2">
|
||||
<object name="exampleJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz3">
|
||||
<property name="JobType" value="Spring.Scheduling.Quartz.Example.ExampleJob, Spring.Scheduling.Quartz.Example" />
|
||||
<!-- We can inject values throgh JobDataMap -->
|
||||
<property name="JobDataAsMap">
|
||||
@@ -17,20 +17,20 @@
|
||||
<property name="UserName" value="Gabriel" />
|
||||
</object>
|
||||
|
||||
<object id="jobDetail" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object id="jobDetail" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<!-- We don't actually need to implement IJob as we can use delegation -->
|
||||
<property name="TargetObject" ref="adminService" />
|
||||
<property name="TargetMethod" value="DoAdminWork" />
|
||||
</object>
|
||||
|
||||
<object id="jobDetailNonConcurrent" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object id="jobDetailNonConcurrent" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="targetObject" ref="adminService" />
|
||||
<property name="targetMethod" value="DoAdminWork" />
|
||||
<!-- Automatic IStatefulJob wrapping -->
|
||||
<property name="concurrent" value="false" />
|
||||
</object>
|
||||
|
||||
<object id="simpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="simpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<!-- see the example of method invoking job above -->
|
||||
<property name="jobDetail" ref="jobDetail" />
|
||||
<!-- 5 seconds -->
|
||||
@@ -40,13 +40,13 @@
|
||||
</object>
|
||||
|
||||
|
||||
<object id="cronTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="cronTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<property name="jobDetail" ref="exampleJob" />
|
||||
<!-- run every 20 second of minute -->
|
||||
<property name="cronExpressionString" value="0/20 * * * * ?" />
|
||||
</object>
|
||||
|
||||
<object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="triggers">
|
||||
<list>
|
||||
<ref object="cronTrigger" />
|
||||
|
||||
@@ -44,7 +44,11 @@
|
||||
|
||||
<ItemGroup Condition="'$(SourceLinkEnabled)' != 'false'">
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-63127-02" PrivateAssets="All"/>
|
||||
</ItemGroup>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" Version="2.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<DebugType>Full</DebugType>
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
using AopAlliance.Intercept;
|
||||
|
||||
using Common.Logging;
|
||||
|
||||
using Spring.Core.TypeConversion;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
using AopAlliance.Intercept;
|
||||
|
||||
using Common.Logging;
|
||||
|
||||
using Spring.Core.TypeConversion;
|
||||
using Spring.Expressions;
|
||||
|
||||
namespace Spring.Aspects
|
||||
@@ -40,22 +40,22 @@ namespace Spring.Aspects
|
||||
/// <remarks>
|
||||
///
|
||||
/// </remarks>
|
||||
/// <author>Mark Pollack</author>
|
||||
/// <author>Mark Pollack</author>
|
||||
[Serializable]
|
||||
public class RetryAdvice : AbstractExceptionHandlerAdvice
|
||||
{
|
||||
///<summary>
|
||||
///The type of the callback that is called for delaying retries.
|
||||
///</summary>
|
||||
public delegate void SleepHandler(TimeSpan duration);
|
||||
|
||||
private static readonly ILog log;
|
||||
private static readonly TimeSpanConverter timeSpanConverter;
|
||||
|
||||
{
|
||||
///<summary>
|
||||
///The type of the callback that is called for delaying retries.
|
||||
///</summary>
|
||||
public delegate void SleepHandler(TimeSpan duration);
|
||||
|
||||
private static readonly ILog log;
|
||||
private static readonly TimeSpanConverter timeSpanConverter;
|
||||
|
||||
static RetryAdvice()
|
||||
{
|
||||
log = LogManager.GetLogger(typeof(RetryAdvice));
|
||||
timeSpanConverter = new TimeSpanConverter();
|
||||
{
|
||||
log = LogManager.GetLogger(typeof(RetryAdvice));
|
||||
timeSpanConverter = new TimeSpanConverter();
|
||||
}
|
||||
|
||||
#region Fields
|
||||
@@ -112,19 +112,20 @@ namespace Spring.Aspects
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new RetryAdvice instance, using <see cref="Thread.Sleep(TimeSpan)"/> for delaying retries
|
||||
/// <summary>
|
||||
/// Creates a new RetryAdvice instance, using <see cref="Thread.Sleep(TimeSpan)"/> for delaying retries
|
||||
/// </summary>
|
||||
public RetryAdvice()
|
||||
:this(new SleepHandler(Thread.Sleep))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new RetryAdvice instance, using any arbitrary callback for delaying retries
|
||||
/// </summary>
|
||||
public RetryAdvice(SleepHandler sleepHandler)
|
||||
{
|
||||
public RetryAdvice()
|
||||
:this(new SleepHandler(Thread.Sleep))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new RetryAdvice instance, using any arbitrary callback for delaying retries
|
||||
/// </summary>
|
||||
public RetryAdvice(SleepHandler sleepHandler)
|
||||
{
|
||||
this.sleepHandler = sleepHandler;
|
||||
}
|
||||
|
||||
#region IMethodInterceptor implementation
|
||||
@@ -211,19 +212,19 @@ namespace Spring.Aspects
|
||||
IExpression expression = Expression.Parse(handler.DelayRateExpression);
|
||||
object result = expression.GetValue(null, callContextDictionary);
|
||||
decimal d = decimal.Parse(result.ToString());
|
||||
decimal d = decimal.Parse(result.ToString());
|
||||
decimal rounded = decimal.Round(d*1000,0);
|
||||
TimeSpan duration = TimeSpan.FromMilliseconds(decimal.ToDouble(rounded));
|
||||
sleepHandler(duration);
|
||||
}
|
||||
catch (InvalidCastException e)
|
||||
{
|
||||
{
|
||||
log.Warn("Was not able to cast expression to decimal [" + handler.DelayRateExpression + "]. Sleeping for 1 second", e);
|
||||
sleepHandler(new TimeSpan(0,0,1));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
{
|
||||
log.Warn("Was not able to evaluate rate expression [" + handler.DelayRateExpression + "]. Sleeping for 1 second", e);
|
||||
log.Warn("Was not able to evaluate rate expression [" + handler.DelayRateExpression + "]. Sleeping for 1 second", e);
|
||||
sleepHandler(new TimeSpan(0,0,1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,18 +342,18 @@ namespace Spring.Aspects
|
||||
RegexOptions options = ((RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline) | RegexOptions.IgnoreCase);
|
||||
Regex reg = new Regex(regexString, options);
|
||||
return reg.Match(actionExpressionString);
|
||||
return reg.Match(actionExpressionString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override in case you need to initialized non-serialized fields on deserialization.
|
||||
/// </summary>
|
||||
protected override void OnDeserialization(object sender)
|
||||
{
|
||||
base.OnDeserialization(sender);
|
||||
if (retryExpression != null)
|
||||
{
|
||||
this.AfterPropertiesSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override in case you need to initialized non-serialized fields on deserialization.
|
||||
/// </summary>
|
||||
protected override void OnDeserialization(object sender)
|
||||
{
|
||||
base.OnDeserialization(sender);
|
||||
if (retryExpression != null)
|
||||
{
|
||||
this.AfterPropertiesSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2011 the original author or authors.
|
||||
*
|
||||
@@ -16,10 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
@@ -30,8 +24,6 @@ using Spring.Core.IO;
|
||||
using Spring.Objects.Factory.Config;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Objects.Factory.Xml
|
||||
{
|
||||
/// <summary>
|
||||
@@ -72,31 +64,38 @@ namespace Spring.Objects.Factory.Xml
|
||||
/// </summary>
|
||||
private const string ConfigParsersSectionName = "spring/parsers";
|
||||
|
||||
#region Fields
|
||||
|
||||
private static IDictionary parsers;
|
||||
private readonly static IDictionary wellknownNamespaceParserTypeNames;
|
||||
private static XmlSchemaSet schemas;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the NamespaceParserRegistry class.
|
||||
/// </summary>
|
||||
static NamespaceParserRegistry()
|
||||
{
|
||||
wellknownNamespaceParserTypeNames = new CaseInsensitiveHashtable();
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/tx"] = "Spring.Transaction.Config.TxNamespaceParser, Spring.Data";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/aop"] = "Spring.Aop.Config.AopNamespaceParser, Spring.Aop";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/context"] = "Spring.Context.Config.ContextNamespaceParser, Spring.Core";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/db"] = "Spring.Data.Config.DatabaseNamespaceParser, Spring.Data";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/database"] = "Spring.Data.Config.DatabaseNamespaceParser, Spring.Data";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/remoting"] = "Spring.Remoting.Config.RemotingNamespaceParser, Spring.Services";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/wcf"] = "Spring.ServiceModel.Config.WcfNamespaceParser, Spring.Services";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/nms"] = "Spring.Messaging.Nms.Config.NmsNamespaceParser, Spring.Messaging.Nms";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/ems"] = "Spring.Messaging.Ems.Config.EmsNamespaceParser, Spring.Messaging.Ems";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/validation"] = "Spring.Validation.Config.ValidationNamespaceParser, Spring.Core";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/nvelocity"] = "Spring.Template.Velocity.Config.TemplateNamespaceParser, Spring.Template.Velocity";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/tx"] =
|
||||
"Spring.Transaction.Config.TxNamespaceParser, Spring.Data";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/aop"] =
|
||||
"Spring.Aop.Config.AopNamespaceParser, Spring.Aop";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/context"] =
|
||||
"Spring.Context.Config.ContextNamespaceParser, Spring.Core";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/db"] =
|
||||
"Spring.Data.Config.DatabaseNamespaceParser, Spring.Data";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/database"] =
|
||||
"Spring.Data.Config.DatabaseNamespaceParser, Spring.Data";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/remoting"] =
|
||||
"Spring.Remoting.Config.RemotingNamespaceParser, Spring.Services";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/wcf"] =
|
||||
"Spring.ServiceModel.Config.WcfNamespaceParser, Spring.Services";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/nms"] =
|
||||
"Spring.Messaging.Nms.Config.NmsNamespaceParser, Spring.Messaging.Nms";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/ems"] =
|
||||
"Spring.Messaging.Ems.Config.EmsNamespaceParser, Spring.Messaging.Ems";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/validation"] =
|
||||
"Spring.Validation.Config.ValidationNamespaceParser, Spring.Core";
|
||||
wellknownNamespaceParserTypeNames["http://www.springframework.net/nvelocity"] =
|
||||
"Spring.Template.Velocity.Config.TemplateNamespaceParser, Spring.Template.Velocity";
|
||||
|
||||
Reset();
|
||||
}
|
||||
@@ -109,7 +108,7 @@ namespace Spring.Objects.Factory.Xml
|
||||
{
|
||||
parsers = new HybridDictionary();
|
||||
schemas = new XmlSchemaSet();
|
||||
schemas.XmlResolver = new XmlResourceUrlResolver();
|
||||
schemas.XmlResolver = new XmlResourceUrlResolver();
|
||||
|
||||
RegisterParser(new ObjectsNamespaceParser());
|
||||
// register custom config parsers
|
||||
@@ -126,7 +125,7 @@ namespace Spring.Objects.Factory.Xml
|
||||
|
||||
if (wellknownNamespaceParserTypeNames.Contains(namespaceUri))
|
||||
{
|
||||
string parserTypeName = (string)wellknownNamespaceParserTypeNames[namespaceUri];
|
||||
string parserTypeName = (string) wellknownNamespaceParserTypeNames[namespaceUri];
|
||||
// assume, that all Spring.XXX assemblies have same version + public key
|
||||
// get the ", Version=x.x.x.x, Culture=neutral, PublicKeyToken=65e474d141e25e07" part of Spring.Core and append it
|
||||
string name = typeof(NamespaceParserRegistry).Assembly.GetName().Name;
|
||||
@@ -138,6 +137,7 @@ namespace Spring.Objects.Factory.Xml
|
||||
RegisterParser(parserType);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ namespace Spring.Objects.Factory.Xml
|
||||
{
|
||||
return "assembly://" + schemaLocationAssemblyHint.Assembly.FullName + schemaLocation;
|
||||
}
|
||||
|
||||
return schemaLocation;
|
||||
}
|
||||
|
||||
@@ -166,21 +167,22 @@ namespace Spring.Objects.Factory.Xml
|
||||
/// </returns>
|
||||
public static INamespaceParser GetParser(string namespaceURI)
|
||||
{
|
||||
INamespaceParser parser = (INamespaceParser)parsers[namespaceURI];
|
||||
INamespaceParser parser = (INamespaceParser) parsers[namespaceURI];
|
||||
if (parser == null)
|
||||
{
|
||||
bool ok = RegisterWellknownNamespaceParserType(namespaceURI);
|
||||
if (ok)
|
||||
{
|
||||
parser = (INamespaceParser)parsers[namespaceURI];
|
||||
|
||||
parser = (INamespaceParser) parsers[namespaceURI];
|
||||
|
||||
//work-around for SPRNET-1277 where we're inconsistent re: exposing /db or /database as the final namespace element
|
||||
if (parser == null && namespaceURI == "http://www.springframework.net/db")
|
||||
{
|
||||
parser = (INamespaceParser)parsers["http://www.springframework.net/database"];
|
||||
parser = (INamespaceParser) parsers["http://www.springframework.net/database"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
@@ -250,7 +252,7 @@ namespace Spring.Objects.Factory.Xml
|
||||
|
||||
if ((typeof(INamespaceParser)).IsAssignableFrom(parserType))
|
||||
{
|
||||
np = (INamespaceParser)ObjectUtils.InstantiateType(parserType);
|
||||
np = (INamespaceParser) ObjectUtils.InstantiateType(parserType);
|
||||
}
|
||||
// TODO (EE): workaround to enable smooth transition between 1.x and 2.0 style namespace handling
|
||||
else if (typeof(IObjectDefinitionParser).IsAssignableFrom(parserType))
|
||||
@@ -264,28 +266,31 @@ namespace Spring.Objects.Factory.Xml
|
||||
throw new ArgumentNullException(
|
||||
"Either default or an explicit namespace value must be specified for a configuration parser.");
|
||||
}
|
||||
|
||||
if (StringUtils.IsNullOrEmpty(namespaceUri))
|
||||
{
|
||||
namespaceUri = defaults.Namespace;
|
||||
}
|
||||
|
||||
if (StringUtils.IsNullOrEmpty(schemaLocation))
|
||||
{
|
||||
schemaLocation = defaults.SchemaLocation;
|
||||
if (defaults.SchemaLocationAssemblyHint != null)
|
||||
{
|
||||
schemaLocation = GetAssemblySchemaLocation(defaults.SchemaLocationAssemblyHint, schemaLocation);
|
||||
schemaLocation =
|
||||
GetAssemblySchemaLocation(defaults.SchemaLocationAssemblyHint, schemaLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IObjectDefinitionParser odParser = (IObjectDefinitionParser)ObjectUtils.InstantiateType(parserType);
|
||||
IObjectDefinitionParser odParser = (IObjectDefinitionParser) ObjectUtils.InstantiateType(parserType);
|
||||
np = new ObjectDefinitionParserNamespaceParser(odParser);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format("The [{0}] Type must implement the INamespaceParser interface.", parserType.Name)
|
||||
, "parserType");
|
||||
string.Format("The [{0}] Type must implement the INamespaceParser interface.", parserType.Name)
|
||||
, "parserType");
|
||||
}
|
||||
|
||||
RegisterParser(np, namespaceUri, schemaLocation);
|
||||
@@ -345,10 +350,12 @@ namespace Spring.Objects.Factory.Xml
|
||||
throw new ArgumentNullException(
|
||||
"Either default or an explicit namespace value must be specified for a configuration parser.");
|
||||
}
|
||||
|
||||
if (StringUtils.IsNullOrEmpty(namespaceUri))
|
||||
{
|
||||
namespaceUri = defaults.Namespace;
|
||||
}
|
||||
|
||||
if (StringUtils.IsNullOrEmpty(schemaLocation))
|
||||
{
|
||||
schemaLocation = defaults.SchemaLocation;
|
||||
@@ -364,14 +371,14 @@ namespace Spring.Objects.Factory.Xml
|
||||
|
||||
// register parser
|
||||
lock (parsers.SyncRoot)
|
||||
lock (schemas)
|
||||
lock (schemas)
|
||||
{
|
||||
parsers[namespaceUri] = parser;
|
||||
if (StringUtils.HasText(schemaLocation) && !schemas.Contains(namespaceUri))
|
||||
{
|
||||
parsers[namespaceUri] = parser;
|
||||
if (StringUtils.HasText(schemaLocation) && !schemas.Contains(namespaceUri))
|
||||
{
|
||||
RegisterSchema(namespaceUri, schemaLocation);
|
||||
}
|
||||
RegisterSchema(namespaceUri, schemaLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -410,13 +417,12 @@ namespace Spring.Objects.Factory.Xml
|
||||
object[] attrs = parserType.GetCustomAttributes(typeof(NamespaceParserAttribute), true);
|
||||
if (attrs.Length > 0)
|
||||
{
|
||||
return (NamespaceParserAttribute)attrs[0];
|
||||
return (NamespaceParserAttribute) attrs[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#region ObjectDefinitionParserNamespaceParser Utility class
|
||||
|
||||
/// <summary>
|
||||
/// Adapts the <see cref="IObjectDefinitionParser"/> interface to <see cref="INamespaceParser"/>.
|
||||
/// Only for smooth transition between 1.x and 2.0 style namespace handling, will be dropped for 2.0
|
||||
@@ -440,12 +446,11 @@ namespace Spring.Objects.Factory.Xml
|
||||
return odParser.ParseElement(element, parserContext);
|
||||
}
|
||||
|
||||
public ObjectDefinitionHolder Decorate(XmlNode node, ObjectDefinitionHolder definition, ParserContext parserContext)
|
||||
public ObjectDefinitionHolder Decorate(XmlNode node, ObjectDefinitionHolder definition,
|
||||
ParserContext parserContext)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -463,7 +463,7 @@ namespace Spring.Data.NHibernate
|
||||
|
||||
TransactionScopeOption txScopeOption = CreateTransactionScopeOptions(definition);
|
||||
TransactionOptions txOptions = CreateTransactionOptions(definition);
|
||||
txObject.TxScopeAdapter.CreateTransactionScope(txScopeOption, txOptions, definition.EnterpriseServicesInteropOption);
|
||||
txObject.TxScopeAdapter.CreateTransactionScope(txScopeOption, txOptions, definition.AsyncFlowOption);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
|
||||
<Description>Interfaces and classes that provide NHibernate 5 support in Spring.Net</Description>
|
||||
<RootNamespace>Spring.Data.NHibernate</RootNamespace>
|
||||
<NoWarn>0618</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2007 the original author or authors.
|
||||
*
|
||||
@@ -16,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Transactions;
|
||||
using Spring.Data.Support;
|
||||
@@ -54,8 +50,6 @@ namespace Spring.Data.Core
|
||||
this.txAdapter = txAdapter;
|
||||
}
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
/// <summary>
|
||||
/// No-op initialization
|
||||
/// </summary>
|
||||
@@ -64,8 +58,6 @@ namespace Spring.Data.Core
|
||||
// placeholder for more advanced configurations.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override object DoGetTransaction()
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject = new PromotableTxScopeTransactionObject();
|
||||
@@ -74,20 +66,21 @@ namespace Spring.Data.Core
|
||||
{
|
||||
txObject.TxScopeAdapter = txAdapter;
|
||||
}
|
||||
|
||||
return txObject;
|
||||
}
|
||||
|
||||
protected override bool IsExistingTransaction(object transaction)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)transaction;
|
||||
return txObject.TxScopeAdapter.IsExistingTransaction;
|
||||
(PromotableTxScopeTransactionObject) transaction;
|
||||
return txObject.TxScopeAdapter.IsExistingTransaction;
|
||||
}
|
||||
|
||||
protected override void DoBegin(object transaction, Spring.Transaction.ITransactionDefinition definition)
|
||||
protected override void DoBegin(object transaction, ITransactionDefinition definition)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)transaction;
|
||||
(PromotableTxScopeTransactionObject) transaction;
|
||||
try
|
||||
{
|
||||
DoTxScopeBegin(txObject, definition);
|
||||
@@ -106,7 +99,7 @@ namespace Spring.Data.Core
|
||||
PromotableTxScopeTransactionObject txMgrStateObject = (PromotableTxScopeTransactionObject) transaction;
|
||||
return txMgrStateObject.TxScopeAdapter;
|
||||
}
|
||||
|
||||
|
||||
protected override void DoResume(object transaction, object suspendedResources)
|
||||
{
|
||||
}
|
||||
@@ -114,7 +107,7 @@ namespace Spring.Data.Core
|
||||
protected override void DoCommit(DefaultTransactionStatus status)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)status.Transaction;
|
||||
(PromotableTxScopeTransactionObject) status.Transaction;
|
||||
try
|
||||
{
|
||||
txObject.TxScopeAdapter.Complete();
|
||||
@@ -122,7 +115,8 @@ namespace Spring.Data.Core
|
||||
}
|
||||
catch (TransactionAbortedException ex)
|
||||
{
|
||||
throw new UnexpectedRollbackException("Transaction unexpectedly rolled back (maybe due to a timeout)", ex);
|
||||
throw new UnexpectedRollbackException("Transaction unexpectedly rolled back (maybe due to a timeout)",
|
||||
ex);
|
||||
}
|
||||
catch (TransactionInDoubtException ex)
|
||||
{
|
||||
@@ -137,54 +131,53 @@ namespace Spring.Data.Core
|
||||
protected override void DoRollback(DefaultTransactionStatus status)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)status.Transaction;
|
||||
(PromotableTxScopeTransactionObject) status.Transaction;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
txObject.TxScopeAdapter.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Spring.Transaction.TransactionSystemException("Failure on Transaction Scope rollback.", e);
|
||||
throw new TransactionSystemException("Failure on Transaction Scope rollback.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void DoSetRollbackOnly(DefaultTransactionStatus status)
|
||||
{
|
||||
if (status.Debug)
|
||||
{
|
||||
log.Debug("Setting transaction rollback-only");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
System.Transactions.Transaction.Current.Rollback();
|
||||
} catch (Exception ex)
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new TransactionSystemException("Failure on System.Transactions.Transaction.Current.Rollback", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ShouldCommitOnGlobalRollbackOnly
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
protected override bool ShouldCommitOnGlobalRollbackOnly => true;
|
||||
|
||||
private void DoTxScopeBegin(PromotableTxScopeTransactionObject txObject,
|
||||
Spring.Transaction.ITransactionDefinition definition)
|
||||
private void DoTxScopeBegin(
|
||||
PromotableTxScopeTransactionObject txObject,
|
||||
ITransactionDefinition definition)
|
||||
{
|
||||
|
||||
TransactionScopeOption txScopeOption = CreateTransactionScopeOptions(definition);
|
||||
TransactionScopeOption txScopeOption = CreateTransactionScopeOptions(definition);
|
||||
TransactionOptions txOptions = CreateTransactionOptions(definition);
|
||||
txObject.TxScopeAdapter.CreateTransactionScope(txScopeOption, txOptions, definition.EnterpriseServicesInteropOption);
|
||||
|
||||
txObject.TxScopeAdapter.CreateTransactionScope(
|
||||
txScopeOption,
|
||||
txOptions,
|
||||
definition.AsyncFlowOption);
|
||||
}
|
||||
|
||||
private static TransactionOptions CreateTransactionOptions(ITransactionDefinition definition)
|
||||
{
|
||||
TransactionOptions txOptions = new TransactionOptions();
|
||||
switch (definition.TransactionIsolationLevel )
|
||||
switch (definition.TransactionIsolationLevel)
|
||||
{
|
||||
case System.Data.IsolationLevel.Chaos:
|
||||
txOptions.IsolationLevel = IsolationLevel.Chaos;
|
||||
@@ -210,9 +203,10 @@ namespace Spring.Data.Core
|
||||
}
|
||||
|
||||
if (definition.TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
|
||||
{
|
||||
{
|
||||
txOptions.Timeout = new TimeSpan(0, 0, definition.TransactionTimeout);
|
||||
}
|
||||
|
||||
return txOptions;
|
||||
}
|
||||
|
||||
@@ -233,10 +227,11 @@ namespace Spring.Data.Core
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Spring.Transaction.TransactionSystemException("Transaction Propagation Behavior" +
|
||||
definition.PropagationBehavior +
|
||||
" not supported by TransactionScope. Use Required or RequiredNew");
|
||||
throw new TransactionSystemException("Transaction Propagation Behavior" +
|
||||
definition.PropagationBehavior +
|
||||
" not supported by TransactionScope. Use Required or RequiredNew");
|
||||
}
|
||||
|
||||
return txScopeOption;
|
||||
}
|
||||
|
||||
@@ -264,22 +259,16 @@ namespace Spring.Data.Core
|
||||
/// <value>The transaction scope adapter.</value>
|
||||
public ITransactionScopeAdapter TxScopeAdapter
|
||||
{
|
||||
get { return txScopeAdapter; }
|
||||
set { txScopeAdapter = value; }
|
||||
get => txScopeAdapter;
|
||||
set => txScopeAdapter = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return whether the transaction is internally marked as rollback-only.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <returns>True of the transaction is marked as rollback-only.</returns>
|
||||
public bool RollbackOnly
|
||||
{
|
||||
get {
|
||||
return txScopeAdapter.RollbackOnly;
|
||||
}
|
||||
}
|
||||
public bool RollbackOnly => txScopeAdapter.RollbackOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,75 +31,45 @@ namespace Spring.Data.Support
|
||||
{
|
||||
private TransactionScope txScope;
|
||||
|
||||
/// <summary>
|
||||
/// Call Complete() on the TransactionScope object created by this instance.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Complete()
|
||||
{
|
||||
txScope.Complete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call Disponse() on the TransactionScope object created by this instance.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
txScope.Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsExistingTransaction => System.Transactions.Transaction.Current != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether there is a new transaction or an existing transaction.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is existing transaction; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsExistingTransaction
|
||||
{
|
||||
get {
|
||||
if (System.Transactions.Transaction.Current != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether rollback only has been called (i.e. Rollback() on the
|
||||
/// Transaction object) and therefore voting that the transaction will be aborted.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if rollback only; otherwise, <c>false</c>.</value>
|
||||
/// <inheritdoc />
|
||||
public bool RollbackOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (System.Transactions.Transaction.Current != null &&
|
||||
System.Transactions.Transaction.Current.TransactionInformation != null &&
|
||||
System.Transactions.Transaction.Current.TransactionInformation.Status == TransactionStatus.Aborted)
|
||||
var transaction = System.Transactions.Transaction.Current;
|
||||
if (transaction != null &&
|
||||
transaction.TransactionInformation != null &&
|
||||
transaction.TransactionInformation.Status == TransactionStatus.Aborted)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the transaction scope.
|
||||
/// </summary>
|
||||
/// <param name="txScopeOption">The tx scope option.</param>
|
||||
/// <param name="txOptions">The tx options.</param>
|
||||
/// <param name="interopOption">The interop option.</param>
|
||||
public void CreateTransactionScope(TransactionScopeOption txScopeOption, TransactionOptions txOptions,
|
||||
EnterpriseServicesInteropOption interopOption)
|
||||
/// <inheritdoc />
|
||||
public void CreateTransactionScope(
|
||||
TransactionScopeOption txScopeOption,
|
||||
TransactionOptions txOptions,
|
||||
TransactionScopeAsyncFlowOption asyncFlowOption)
|
||||
{
|
||||
txScope = new TransactionScope(txScopeOption, txOptions, interopOption);
|
||||
txScope = new TransactionScope(txScopeOption, txOptions, asyncFlowOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,21 +35,22 @@ namespace Spring.Data.Support
|
||||
/// </summary>
|
||||
/// <param name="txScopeOption">The tx scope option.</param>
|
||||
/// <param name="txOptions">The tx options.</param>
|
||||
/// <param name="interopOption">The interop option.</param>
|
||||
void CreateTransactionScope(TransactionScopeOption txScopeOption, TransactionOptions txOptions, EnterpriseServicesInteropOption interopOption);
|
||||
/// <param name="asyncFlowOption">The async flow option.</param>
|
||||
void CreateTransactionScope(
|
||||
TransactionScopeOption txScopeOption,
|
||||
TransactionOptions txOptions,
|
||||
TransactionScopeAsyncFlowOption asyncFlowOption);
|
||||
|
||||
/// <summary>
|
||||
/// Call Complete() on the TransactionScope object created by this instance.
|
||||
/// </summary>
|
||||
void Complete();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Call Disponse() on the TransactionScope object created by this instance.
|
||||
/// Call Dispose() on the TransactionScope object created by this instance.
|
||||
/// </summary>
|
||||
void Dispose();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether there is a new transaction or an existing transaction.
|
||||
/// </summary>
|
||||
@@ -58,13 +59,11 @@ namespace Spring.Data.Support
|
||||
/// </value>
|
||||
bool IsExistingTransaction { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether rollback only has been called (i.e. Rollback() on the
|
||||
/// Transaction object) and therefore voting that the transaction will be aborted.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if rollback only; otherwise, <c>false</c>.</value>
|
||||
bool RollbackOnly { get; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,9 +111,9 @@ namespace Spring.Transaction
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enterprise services interop option.
|
||||
/// Gets the async flow option.
|
||||
/// </summary>
|
||||
/// <value>The enterprise services interop option.</value>
|
||||
System.Transactions.EnterpriseServicesInteropOption EnterpriseServicesInteropOption { get;}
|
||||
/// <value>The async flow option.</value>
|
||||
System.Transactions.TransactionScopeAsyncFlowOption AsyncFlowOption { get;}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Spring.Transaction.Interceptor
|
||||
rbta.TransactionIsolationLevel = ta.IsolationLevel;
|
||||
rbta.ReadOnly = ta.ReadOnly;
|
||||
rbta.TransactionTimeout = ta.Timeout;
|
||||
rbta.EnterpriseServicesInteropOption = ta.EnterpriseServicesInteropOption;
|
||||
rbta.AsyncFlowOption = ta.AsyncFlowOption;
|
||||
|
||||
Type[] rbf = ta.RollbackFor;
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
@@ -16,83 +14,83 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Spring.Transaction.Support;
|
||||
|
||||
namespace Spring.Transaction.Interceptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Transaction attribute approach to rolling back on all exceptions, no other
|
||||
/// exceptions by default.
|
||||
/// </summary>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Griffin Caprio (.NET)</author>
|
||||
public class DefaultTransactionAttribute : DefaultTransactionDefinition, ITransactionAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Prefix for rollback-on-exception rules in description strings.
|
||||
/// </summary>
|
||||
public static readonly string ROLLBACK_RULE_PREFIX = "-";
|
||||
/// <summary>
|
||||
/// Transaction attribute approach to rolling back on all exceptions, no other
|
||||
/// exceptions by default.
|
||||
/// </summary>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Griffin Caprio (.NET)</author>
|
||||
public class DefaultTransactionAttribute : DefaultTransactionDefinition, ITransactionAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Prefix for rollback-on-exception rules in description strings.
|
||||
/// </summary>
|
||||
public static readonly string ROLLBACK_RULE_PREFIX = "-";
|
||||
|
||||
/// <summary>
|
||||
/// Prefix for commit-on-exception rules in description strings.
|
||||
/// </summary>
|
||||
public static readonly string COMMIT_RULE_PREFIX = "+";
|
||||
/// <summary>
|
||||
/// Prefix for commit-on-exception rules in description strings.
|
||||
/// </summary>
|
||||
public static readonly string COMMIT_RULE_PREFIX = "+";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Transaction.Interceptor.DefaultTransactionAttribute"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
public DefaultTransactionAttribute() {}
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Transaction.Interceptor.DefaultTransactionAttribute"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
public DefaultTransactionAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Transaction.Interceptor.DefaultTransactionAttribute"/>
|
||||
/// class, setting the propagation behavior to the supplied value.
|
||||
/// </summary>
|
||||
/// <param name="propagationBehavior">
|
||||
/// The desired transaction propagation behaviour.
|
||||
/// </param>
|
||||
public DefaultTransactionAttribute( TransactionPropagation propagationBehavior )
|
||||
: base (propagationBehavior) {}
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Transaction.Interceptor.DefaultTransactionAttribute"/>
|
||||
/// class, setting the propagation behavior to the supplied value.
|
||||
/// </summary>
|
||||
/// <param name="propagationBehavior">
|
||||
/// The desired transaction propagation behaviour.
|
||||
/// </param>
|
||||
public DefaultTransactionAttribute(TransactionPropagation propagationBehavior)
|
||||
: base(propagationBehavior)
|
||||
{
|
||||
}
|
||||
|
||||
#region ITransactionAttribute Members
|
||||
/// <summary>
|
||||
/// Decides if rollback is required for the supplied <paramref name="exception"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// The default behavior is to rollback on any exception.
|
||||
/// Consistent with <see cref="Spring.Transaction.Support.TransactionTemplate"/>'s behavior.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <param name="exception">The <see cref="System.Exception"/> to evaluate.</param>
|
||||
/// <returns>True if the exception causes a rollback, false otherwise.</returns>
|
||||
public virtual bool RollbackOn(Exception exception)
|
||||
{
|
||||
return ( true );
|
||||
}
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Decides if rollback is required for the supplied <paramref name="exception"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// The default behavior is to rollback on any exception.
|
||||
/// Consistent with <see cref="Spring.Transaction.Support.TransactionTemplate"/>'s behavior.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <param name="exception">The <see cref="System.Exception"/> to evaluate.</param>
|
||||
/// <returns>True if the exception causes a rollback, false otherwise.</returns>
|
||||
public virtual bool RollbackOn(Exception exception)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a description of this transaction attribute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// The format matches the one used by the
|
||||
/// <see cref="Spring.Transaction.Interceptor.TransactionAttributeEditor"/>,
|
||||
/// to be able to feed any result into a <see cref="Spring.Transaction.Interceptor.ITransactionAttribute"/>
|
||||
/// instance's properties.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public override string ToString()
|
||||
{
|
||||
string result = DefinitionDescription;
|
||||
result += "," + ROLLBACK_RULE_PREFIX + "System.Exception";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Return a description of this transaction attribute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// The format matches the one used by the
|
||||
/// <see cref="Spring.Transaction.Interceptor.TransactionAttributeEditor"/>,
|
||||
/// to be able to feed any result into a <see cref="Spring.Transaction.Interceptor.ITransactionAttribute"/>
|
||||
/// instance's properties.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public override string ToString()
|
||||
{
|
||||
string result = DefinitionDescription;
|
||||
result += "," + ROLLBACK_RULE_PREFIX + "System.Exception";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,8 @@ namespace Spring.Transaction.Interceptor
|
||||
/// </summary>
|
||||
public class DelegatingTransactionAttributeWithName : ITransactionAttribute
|
||||
{
|
||||
private ITransactionAttribute targetAttribute;
|
||||
private string joinpointIdentification;
|
||||
private readonly ITransactionAttribute targetAttribute;
|
||||
private readonly string joinpointIdentification;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DelegatingTransactionAttributeWithName"/> class.
|
||||
@@ -61,10 +61,7 @@ namespace Spring.Transaction.Interceptor
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation"/>.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public TransactionPropagation PropagationBehavior
|
||||
{
|
||||
get { return targetAttribute.PropagationBehavior; }
|
||||
}
|
||||
public TransactionPropagation PropagationBehavior => targetAttribute.PropagationBehavior;
|
||||
|
||||
/// <summary>
|
||||
/// Return the isolation level of type <see cref="System.Data.IsolationLevel"/>.
|
||||
@@ -82,75 +79,19 @@ namespace Spring.Transaction.Interceptor
|
||||
/// <see cref="System.Data.IsolationLevel.Unspecified"/>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public IsolationLevel TransactionIsolationLevel
|
||||
{
|
||||
get { return targetAttribute.TransactionIsolationLevel; }
|
||||
}
|
||||
public IsolationLevel TransactionIsolationLevel => targetAttribute.TransactionIsolationLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Return the transaction timeout.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Must return a number of seconds, or -1.
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// Note that a transaction manager that does not support timeouts will
|
||||
/// throw an exception when given any other timeout than -1.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public int TransactionTimeout
|
||||
{
|
||||
get { return targetAttribute.TransactionTimeout; }
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public int TransactionTimeout => targetAttribute.TransactionTimeout;
|
||||
|
||||
/// <summary>
|
||||
/// Get whether to optimize as read-only transaction.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This just serves as hint for the actual transaction subsystem,
|
||||
/// it will <i>not necessarily</i> cause failure of write accesses.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// A transaction manager that cannot interpret the read-only hint
|
||||
/// will <i>not</i> throw an exception when given <c>ReadOnly=true</c>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public bool ReadOnly
|
||||
{
|
||||
get { return targetAttribute.ReadOnly; }
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public bool ReadOnly => targetAttribute.ReadOnly;
|
||||
|
||||
/// <summary>
|
||||
/// Return the name of this transaction.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <remarks>
|
||||
/// The exposed name will be the fully
|
||||
/// qualified type name + "." method name + assembly (by default).
|
||||
/// </remarks>
|
||||
public string Name
|
||||
{
|
||||
get { return joinpointIdentification; }
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public string Name => joinpointIdentification;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enterprise services interop option.
|
||||
/// </summary>
|
||||
/// <value>The enterprise services interop option.</value>
|
||||
public EnterpriseServicesInteropOption EnterpriseServicesInteropOption
|
||||
{
|
||||
get { return targetAttribute.EnterpriseServicesInteropOption; }
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public TransactionScopeAsyncFlowOption AsyncFlowOption => targetAttribute.AsyncFlowOption;
|
||||
|
||||
/// <summary>
|
||||
/// Return a description of this transaction attribute.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2011 the original author or authors.
|
||||
*
|
||||
@@ -16,30 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using Spring.Transaction.Support;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Transaction.Interceptor
|
||||
{
|
||||
/// <summary>
|
||||
/// .NET Attribute for describing transactional behavior of methods in a class.
|
||||
/// </summary>
|
||||
/// <remarks>This attribute type is generally directly comparable
|
||||
/// to Spring's <see cref="RuleBasedTransactionAttribute"/> class and
|
||||
/// in fact <see cref="AttributesTransactionAttributeSource"/> will
|
||||
/// <summary>
|
||||
/// .NET Attribute for describing transactional behavior of methods in a class.
|
||||
/// </summary>
|
||||
/// <remarks>This attribute type is generally directly comparable
|
||||
/// to Spring's <see cref="RuleBasedTransactionAttribute"/> class and
|
||||
/// in fact <see cref="AttributesTransactionAttributeSource"/> will
|
||||
/// directly convert the data to a <see cref="RuleBasedTransactionAttribute"/>
|
||||
/// so that Spring's transaction support code does not have to know about
|
||||
/// attributes. If no rules are relevant to the exception it will be treaded
|
||||
/// like DefaultTransactionAttribute, (rolling back on all exceptions).
|
||||
/// <para>
|
||||
/// <para>
|
||||
/// The default property values are TransactionPropagation.Required, IsolationLevel.ReadCommitted,
|
||||
/// DefaultTransactionDefinition.TIMEOUT_DEFAULT (can be changed, by default is the default
|
||||
/// value of the underlying transaction subsystem)
|
||||
@@ -47,32 +38,27 @@ namespace Spring.Transaction.Interceptor
|
||||
/// types.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
|
||||
Inherited = true)]
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
|
||||
Inherited = true)]
|
||||
[Serializable]
|
||||
public class TransactionAttribute : Attribute
|
||||
{
|
||||
#region Fields
|
||||
public class TransactionAttribute : Attribute
|
||||
{
|
||||
private TransactionPropagation _transactionPropagation = TransactionPropagation.Required;
|
||||
private IsolationLevel _isolationLevel = IsolationLevel.ReadCommitted;
|
||||
private int _timeout = DefaultTransactionDefinition.TIMEOUT_DEFAULT;
|
||||
private bool _readOnly = false;
|
||||
private Type[] _rollbackTypes = Type.EmptyTypes;
|
||||
private Type[] _noRollbackTypes = Type.EmptyTypes;
|
||||
private System.Transactions.EnterpriseServicesInteropOption _esInteropOption =
|
||||
System.Transactions.EnterpriseServicesInteropOption.Automatic;
|
||||
|
||||
#endregion
|
||||
private System.Transactions.TransactionScopeAsyncFlowOption _asyncFlowOption = System.Transactions.TransactionScopeAsyncFlowOption.Enabled;
|
||||
|
||||
#region Constructor (s)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TransactionAttribute"/> class.
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TransactionAttribute"/> class.
|
||||
/// </summary>
|
||||
public TransactionAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
public TransactionAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TransactionAttribute"/> class.
|
||||
@@ -89,7 +75,7 @@ namespace Spring.Transaction.Interceptor
|
||||
/// <param name="transactionPropagation">The transaction propagation.</param>
|
||||
/// <param name="isolationLevel">The isolation level.</param>
|
||||
public TransactionAttribute(TransactionPropagation transactionPropagation,
|
||||
IsolationLevel isolationLevel) : this(transactionPropagation)
|
||||
IsolationLevel isolationLevel) : this(transactionPropagation)
|
||||
{
|
||||
_isolationLevel = isolationLevel;
|
||||
}
|
||||
@@ -103,51 +89,41 @@ namespace Spring.Transaction.Interceptor
|
||||
_isolationLevel = isolationLevel;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transaction propagation.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to TransactionPropagation.Required</remarks>
|
||||
/// <value>The transaction propagation.</value>
|
||||
public TransactionPropagation TransactionPropagation
|
||||
{
|
||||
get { return _transactionPropagation; }
|
||||
}
|
||||
public TransactionPropagation TransactionPropagation => _transactionPropagation;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the isolation level.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to IsolationLevel.Unspecified</remarks>
|
||||
/// <value>The isolation level.</value>
|
||||
public IsolationLevel IsolationLevel
|
||||
{
|
||||
get { return _isolationLevel; }
|
||||
}
|
||||
public IsolationLevel IsolationLevel => _isolationLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timeout.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to the default timeout of the underlying transaction system.</remarks>
|
||||
/// <value>The timeout.</value>
|
||||
public int Timeout
|
||||
{
|
||||
get { return _timeout; }
|
||||
set { _timeout = value; }
|
||||
}
|
||||
public int Timeout
|
||||
{
|
||||
get => _timeout;
|
||||
set => _timeout = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the transaction is readonly.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to false</remarks>
|
||||
/// <value><c>true</c> if read-only; otherwise, <c>false</c>.</value>
|
||||
public bool ReadOnly
|
||||
{
|
||||
get { return _readOnly; }
|
||||
set { _readOnly = value; }
|
||||
}
|
||||
public bool ReadOnly
|
||||
{
|
||||
get => _readOnly;
|
||||
set => _readOnly = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the zero or more exception types which
|
||||
@@ -157,11 +133,11 @@ namespace Spring.Transaction.Interceptor
|
||||
/// <remarks>This is the preferred way to construct a rollback rule,
|
||||
/// matching the exception class and subclasses.</remarks>
|
||||
/// <value>The rollback types.</value>
|
||||
public Type[] RollbackFor
|
||||
{
|
||||
get { return _rollbackTypes; }
|
||||
set { _rollbackTypes = value; }
|
||||
}
|
||||
public Type[] RollbackFor
|
||||
{
|
||||
get => _rollbackTypes;
|
||||
set => _rollbackTypes = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets zero or more exceptions types which
|
||||
@@ -171,27 +147,20 @@ namespace Spring.Transaction.Interceptor
|
||||
/// <remarks>This is the preferred way to construct a rollback rule,
|
||||
/// matching the exception type.</remarks>
|
||||
/// <value>The no rollback for.</value>
|
||||
public Type[] NoRollbackFor
|
||||
{
|
||||
get { return _noRollbackTypes; }
|
||||
set { _noRollbackTypes = value; }
|
||||
}
|
||||
public Type[] NoRollbackFor
|
||||
{
|
||||
get => _noRollbackTypes;
|
||||
set => _noRollbackTypes = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the enterprise services interop option.
|
||||
/// Gets the async flow option.
|
||||
/// </summary>
|
||||
/// <value>The enterprise services interop option.</value>
|
||||
public System.Transactions.EnterpriseServicesInteropOption EnterpriseServicesInteropOption
|
||||
{
|
||||
get { return _esInteropOption;}
|
||||
set { _esInteropOption = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
/// <value>The async flow option.</value>
|
||||
public System.Transactions.TransactionScopeAsyncFlowOption AsyncFlowOption
|
||||
{
|
||||
get => _asyncFlowOption;
|
||||
set => _asyncFlowOption = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
@@ -16,174 +14,170 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Transactions;
|
||||
|
||||
namespace Spring.Transaction.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of the <see cref="Spring.Transaction.ITransactionDefinition"/>
|
||||
/// interface, offering object-style configuration and sensible default values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Base class for both <see cref="System.SystemException"/> and
|
||||
/// <see cref="Spring.Transaction.Interceptor.DefaultTransactionAttribute"/>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Griffin Caprio (.NET)</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
[Serializable]
|
||||
public class DefaultTransactionDefinition : ITransactionDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Prefix for Propagation settings.
|
||||
/// </summary>
|
||||
public static readonly string PROPAGATION_CONSTANT_PREFIX = "PROPAGATION";
|
||||
/// <summary>
|
||||
/// Default implementation of the <see cref="Spring.Transaction.ITransactionDefinition"/>
|
||||
/// interface, offering object-style configuration and sensible default values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Base class for both <see cref="System.SystemException"/> and
|
||||
/// <see cref="Spring.Transaction.Interceptor.DefaultTransactionAttribute"/>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Griffin Caprio (.NET)</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
[Serializable]
|
||||
public class DefaultTransactionDefinition : ITransactionDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Prefix for Propagation settings.
|
||||
/// </summary>
|
||||
public static readonly string PROPAGATION_CONSTANT_PREFIX = "PROPAGATION";
|
||||
|
||||
/// <summary>
|
||||
/// Prefix for IsolationLevel settings.
|
||||
/// </summary>
|
||||
public static readonly string ISOLATION_CONSTANT_PREFIX = "ISOLATION";
|
||||
/// <summary>
|
||||
/// Prefix for IsolationLevel settings.
|
||||
/// </summary>
|
||||
public static readonly string ISOLATION_CONSTANT_PREFIX = "ISOLATION";
|
||||
|
||||
/// <summary>
|
||||
/// Prefix for transaction timeout values in description strings.
|
||||
/// </summary>
|
||||
public static readonly string TIMEOUT_PREFIX = "timeout_";
|
||||
/// <summary>
|
||||
/// Prefix for transaction timeout values in description strings.
|
||||
/// </summary>
|
||||
public static readonly string TIMEOUT_PREFIX = "timeout_";
|
||||
|
||||
/// <summary>
|
||||
/// Marker for read-only transactions in description strings.
|
||||
/// </summary>
|
||||
public static readonly string READ_ONLY_MARKER = "readOnly";
|
||||
/// <summary>
|
||||
/// Marker for read-only transactions in description strings.
|
||||
/// </summary>
|
||||
public static readonly string READ_ONLY_MARKER = "readOnly";
|
||||
|
||||
/// <summary>
|
||||
/// The default transaction timeout.
|
||||
/// </summary>
|
||||
public const int TIMEOUT_DEFAULT = -1;
|
||||
/// <summary>
|
||||
/// The default transaction timeout.
|
||||
/// </summary>
|
||||
public const int TIMEOUT_DEFAULT = -1;
|
||||
|
||||
//TODO Refactoring to sync with Spring 2.0 for nt/enums for various default values.
|
||||
|
||||
private TransactionPropagation _transactionPropagation = TransactionPropagation.Required;
|
||||
private IsolationLevel _transactionIsolationLevel = IsolationLevel.ReadCommitted;
|
||||
private int _timeout = DefaultTransactionDefinition.TIMEOUT_DEFAULT;
|
||||
private bool _readOnly = false;
|
||||
//TODO Refactoring to sync with Spring 2.0 for nt/enums for various default values.
|
||||
|
||||
private TransactionPropagation _transactionPropagation = TransactionPropagation.Required;
|
||||
private System.Data.IsolationLevel _transactionIsolationLevel = System.Data.IsolationLevel.ReadCommitted;
|
||||
private int _timeout = TIMEOUT_DEFAULT;
|
||||
private bool _readOnly = false;
|
||||
private string _name = null;
|
||||
private System.Transactions.EnterpriseServicesInteropOption _esInteropOption;
|
||||
|
||||
/// <summary>
|
||||
private System.Transactions.TransactionScopeAsyncFlowOption _asyncFlowOption = TransactionScopeAsyncFlowOption.Enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition"/> class.
|
||||
/// </summary>
|
||||
public DefaultTransactionDefinition() {}
|
||||
/// </summary>
|
||||
public DefaultTransactionDefinition()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition"/> class
|
||||
/// with the supplied <see cref="Spring.Transaction.TransactionPropagation"/>
|
||||
/// behaviour.
|
||||
/// </summary>
|
||||
/// <param name="transactionPropagation">
|
||||
/// The desired <see cref="Spring.Transaction.TransactionPropagation"/> behavior.
|
||||
/// </param>
|
||||
public DefaultTransactionDefinition( TransactionPropagation transactionPropagation )
|
||||
{
|
||||
_transactionPropagation = transactionPropagation;
|
||||
}
|
||||
|
||||
#region ITransactionDefinition Members
|
||||
/// </summary>
|
||||
/// <param name="transactionPropagation">
|
||||
/// The desired <see cref="Spring.Transaction.TransactionPropagation"/> behavior.
|
||||
/// </param>
|
||||
public DefaultTransactionDefinition(TransactionPropagation transactionPropagation)
|
||||
{
|
||||
_transactionPropagation = transactionPropagation;
|
||||
}
|
||||
|
||||
// TODO change method name to same as type returned (TransactionPropagation)
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets / Sets the <see cref="Spring.Transaction.TransactionPropagation">propagation</see>
|
||||
/// behavior.
|
||||
/// </summary>
|
||||
public TransactionPropagation PropagationBehavior
|
||||
{
|
||||
get { return _transactionPropagation; }
|
||||
set { _transactionPropagation = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets / Sets the <see cref="Spring.Transaction.TransactionPropagation">propagation</see>
|
||||
/// behavior.
|
||||
/// </summary>
|
||||
public TransactionPropagation PropagationBehavior
|
||||
{
|
||||
get => _transactionPropagation;
|
||||
set => _transactionPropagation = value;
|
||||
}
|
||||
|
||||
// TODO change method name to same as type returned (TransactionPropagation)
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return the isolation level of type <see cref="System.Data.IsolationLevel"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Note that a transaction manager that does not support custom isolation levels
|
||||
/// will throw an exception when given any other level than
|
||||
/// <see cref="System.Data.IsolationLevel.Unspecified"/>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public IsolationLevel TransactionIsolationLevel
|
||||
{
|
||||
get { return _transactionIsolationLevel; }
|
||||
set { _transactionIsolationLevel = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Return the isolation level of type <see cref="System.Data.IsolationLevel"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Note that a transaction manager that does not support custom isolation levels
|
||||
/// will throw an exception when given any other level than
|
||||
/// <see cref="System.Data.IsolationLevel.Unspecified"/>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public System.Data.IsolationLevel TransactionIsolationLevel
|
||||
{
|
||||
get => _transactionIsolationLevel;
|
||||
set => _transactionIsolationLevel = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the transaction timeout.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Must return a number of seconds, or -1.
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// Note that a transaction manager that does not support timeouts will
|
||||
/// throw an exception when given any other timeout than -1.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public int TransactionTimeout
|
||||
{
|
||||
get { return _timeout; }
|
||||
set
|
||||
{
|
||||
if ( value < DefaultTransactionDefinition.TIMEOUT_DEFAULT )
|
||||
{
|
||||
throw new ArgumentException( "Timeout must be a positive integer or DefaultTransactionDefinition.TIMEOUT_DEFAULT" );
|
||||
}
|
||||
_timeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get whether to optimize as read-only transaction.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This just serves as hint for the actual transaction subsystem,
|
||||
/// it will <i>not necessarily</i> cause failure of write accesses.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// A transaction manager that cannot interpret the read-only hint
|
||||
/// will <i>not</i> throw an exception when given <c>ReadOnly=true</c>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public bool ReadOnly
|
||||
{
|
||||
get { return _readOnly; }
|
||||
set { _readOnly = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Return the transaction timeout.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Must return a number of seconds, or -1.
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// Note that a transaction manager that does not support timeouts will
|
||||
/// throw an exception when given any other timeout than -1.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public int TransactionTimeout
|
||||
{
|
||||
get => _timeout;
|
||||
set
|
||||
{
|
||||
if (value < TIMEOUT_DEFAULT)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Timeout must be a positive integer or DefaultTransactionDefinition.TIMEOUT_DEFAULT");
|
||||
}
|
||||
|
||||
_timeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get whether to optimize as read-only transaction.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This just serves as hint for the actual transaction subsystem,
|
||||
/// it will <i>not necessarily</i> cause failure of write accesses.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Only makes sense in combination with
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.Required"/> and
|
||||
/// <see cref="Spring.Transaction.TransactionPropagation.RequiresNew"/>.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// A transaction manager that cannot interpret the read-only hint
|
||||
/// will <i>not</i> throw an exception when given <c>ReadOnly=true</c>.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public bool ReadOnly
|
||||
{
|
||||
get => _readOnly;
|
||||
set => _readOnly = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the name of this transaction. Can be null.
|
||||
@@ -195,89 +189,86 @@ namespace Spring.Transaction.Support
|
||||
/// declarative transactions, the exposed name will be the fully
|
||||
/// qualified type name + "." method name + assembly (by default).
|
||||
/// </remarks>
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set { _name = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enterprise services interop option.
|
||||
/// </summary>
|
||||
/// <value>The enterprise services interop option.</value>
|
||||
public System.Transactions.EnterpriseServicesInteropOption EnterpriseServicesInteropOption
|
||||
public string Name
|
||||
{
|
||||
get { return _esInteropOption; }
|
||||
set { _esInteropOption = value; }
|
||||
get => _name;
|
||||
set => _name = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <inheritdoc />
|
||||
public System.Transactions.TransactionScopeAsyncFlowOption AsyncFlowOption
|
||||
{
|
||||
get => _asyncFlowOption;
|
||||
set => _asyncFlowOption = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// An override of the default <see cref="System.Object.Equals(object)"/> method.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="System.Object"/> to compare to.</param>
|
||||
/// <returns>True if the objects are equal.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return ( obj is ITransactionDefinition ) && ToString().Equals( obj.ToString() );
|
||||
}
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="System.Object"/> to compare to.</param>
|
||||
/// <returns>True if the objects are equal.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is ITransactionDefinition) && ToString().Equals(obj.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// An override of the default <see cref="System.Object.GetHashCode"/> method that returns the
|
||||
/// hashcode of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The hashcode of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The hashcode of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ToString().GetHashCode();
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ToString().GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An override of the default <see cref="System.Object.ToString"/> method that returns a string
|
||||
/// representation of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// An override of the default <see cref="System.Object.ToString"/> method that returns a string
|
||||
/// representation of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A string representation of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return DefinitionDescription;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return DefinitionDescription;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> representation of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </summary>
|
||||
protected string DefinitionDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append( PROPAGATION_CONSTANT_PREFIX +"_" + PropagationBehavior );
|
||||
builder.Append( "," );
|
||||
builder.Append( ISOLATION_CONSTANT_PREFIX + "_" +TransactionIsolationLevel );
|
||||
if ( TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT )
|
||||
{
|
||||
builder.Append( ",timeout_" + _timeout );
|
||||
}
|
||||
if ( ReadOnly )
|
||||
{
|
||||
builder.Append( ",readOnly" );
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> representation of the
|
||||
/// <see cref="Spring.Transaction.Support.DefaultTransactionDefinition.DefinitionDescription"/>
|
||||
/// property.
|
||||
/// </summary>
|
||||
protected string DefinitionDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append(PROPAGATION_CONSTANT_PREFIX + "_" + PropagationBehavior);
|
||||
builder.Append(",");
|
||||
builder.Append(ISOLATION_CONSTANT_PREFIX + "_" + TransactionIsolationLevel);
|
||||
if (TransactionTimeout != TIMEOUT_DEFAULT)
|
||||
{
|
||||
builder.Append(",timeout_" + _timeout);
|
||||
}
|
||||
|
||||
if (ReadOnly)
|
||||
{
|
||||
builder.Append(",readOnly");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 System.Threading;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
using Quartz.Util;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// JobFactory implementation that supports <see cref="ThreadStart" />
|
||||
/// objects as well as standard Quartz <see cref="IJob" /> instances.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="DelegatingJob" />
|
||||
/// <seealso cref="AdaptJob(object)" />
|
||||
public class AdaptableJobFactory : IJobFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by the scheduler at the time of the trigger firing, in order to
|
||||
/// produce a <see cref="IJob"/> instance on which to call Execute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It should be extremely rare for this method to throw an exception -
|
||||
/// basically only the the case where there is no way at all to instantiate
|
||||
/// and prepare the Job for execution. When the exception is thrown, the
|
||||
/// Scheduler will move all triggers associated with the Job into the
|
||||
/// <see cref="TriggerState.Error"/> state, which will require human
|
||||
/// intervention (e.g. an application restart after fixing whatever
|
||||
/// configuration problem led to the issue wih instantiating the Job.
|
||||
/// </remarks>
|
||||
/// <param name="bundle">The TriggerFiredBundle from which the <see cref="IJobDetail"/>
|
||||
/// and other info relating to the trigger firing can be obtained.</param>
|
||||
/// <param name="scheduler">The scheduler instance.</param>
|
||||
/// <returns>the newly instantiated Job</returns>
|
||||
/// <throws>SchedulerException if there is a problem instantiating the Job.</throws>
|
||||
public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
|
||||
{
|
||||
try
|
||||
{
|
||||
object jobObject = CreateJobInstance(bundle);
|
||||
return AdaptJob(jobObject);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new SchedulerException("Job instantiation failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the the job factory to destroy/cleanup the job if needed.
|
||||
/// </summary>
|
||||
public virtual void ReturnJob(IJob job)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the specified job class.
|
||||
/// <p>
|
||||
/// Can be overridden to post-process the job instance.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <param name="bundle">
|
||||
/// The TriggerFiredBundle from which the JobDetail
|
||||
/// and other info relating to the trigger firing can be obtained.
|
||||
/// </param>
|
||||
/// <returns>The job instance.</returns>
|
||||
protected virtual object CreateJobInstance(TriggerFiredBundle bundle)
|
||||
{
|
||||
return ObjectUtils.InstantiateType<object>(bundle.JobDetail.JobType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapt the given job object to the Quartz Job interface.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default implementation supports straight Quartz Jobs
|
||||
/// as well as Runnables, which get wrapped in a DelegatingJob.
|
||||
/// </remarks>
|
||||
/// <param name="jobObject">
|
||||
/// The original instance of the specified job class.
|
||||
/// </param>
|
||||
/// <returns>The adapted Quartz Job instance.</returns>
|
||||
/// <seealso cref="DelegatingJob" />
|
||||
protected virtual IJob AdaptJob(object jobObject)
|
||||
{
|
||||
if (jobObject is IJob)
|
||||
{
|
||||
return (IJob)jobObject;
|
||||
}
|
||||
if (jobObject is ThreadStart)
|
||||
{
|
||||
return new DelegatingJob((ThreadStart)jobObject);
|
||||
}
|
||||
if (jobObject is IThreadRunnable)
|
||||
{
|
||||
return new DelegatingJob(((IThreadRunnable)jobObject).Run);
|
||||
}
|
||||
|
||||
string message = string.Format("Unable to execute job class [{0}]: only [IJob] and [ThreadStart] supported.", jobObject.GetType().FullName);
|
||||
throw new ArgumentException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Quartz;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to be implemented by Quartz Triggers that are aware
|
||||
/// of the JobDetail object that they are associated with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// SchedulerFactoryObject will auto-detect Triggers that implement this
|
||||
/// interface and register them for the respective JobDetail accordingly.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// The alternative is to configure a Trigger for a Job name and group:
|
||||
/// This involves the need to register the JobDetail object separately
|
||||
/// with SchedulerFactoryObject.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SchedulerAccessor.Triggers" />
|
||||
/// <seealso cref="SchedulerAccessor.JobDetails" />
|
||||
public interface IJobDetailAwareTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the JobDetail that this Trigger is associated with.
|
||||
/// </summary>
|
||||
/// <returns>The associated JobDetail, or <code>null</code> if none</returns>
|
||||
IJobDetail JobDetail { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Quartz;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Callback interface to be implemented by Spring-managed
|
||||
/// Quartz artifacts that need access to the SchedulerContext
|
||||
/// (without having natural access to it).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently only supported for custom JobFactory implementations
|
||||
/// that are passed in via Spring's SchedulerFactoryObject.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="IJobFactory" />
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public interface ISchedulerContextAware
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the SchedulerContext of the current Quartz Scheduler.
|
||||
/// </summary>
|
||||
/// <seealso cref="IScheduler.Context" />
|
||||
SchedulerContext SchedulerContext { set; }
|
||||
}
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 System.Collections;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Spring.Context;
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Convenience subclass of Quartz' JobDetail class that eases properties based
|
||||
/// usage.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="IJobDetail" /> itself is already a object but lacks
|
||||
/// sensible defaults. This class uses the Spring object name as job name,
|
||||
/// and the Quartz default group ("DEFAULT") as job group if not specified.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="IJobDetail.Key" />
|
||||
/// <seealso cref="SchedulerConstants.DefaultGroup" />
|
||||
public class JobDetailObject : JobDetailImpl, IObjectNameAware, IApplicationContextAware, IInitializingObject
|
||||
{
|
||||
private Type actualJobType;
|
||||
private string objectName;
|
||||
private IApplicationContext applicationContext;
|
||||
private string applicationContextJobDataKey;
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to support any job class, to allow a custom JobFactory
|
||||
/// to adapt the given job class to the Quartz Job interface.
|
||||
/// </summary>
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public override Type JobType
|
||||
{
|
||||
get { return (actualJobType ?? base.JobType); }
|
||||
|
||||
set
|
||||
{
|
||||
if (value != null && !typeof (IJob).IsAssignableFrom(value))
|
||||
{
|
||||
base.JobType = typeof (DelegatingJob);
|
||||
actualJobType = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.JobType = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register objects in the JobDataMap via a given Map.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These objects will be available to this Job only,
|
||||
/// in contrast to objects in the SchedulerContext.
|
||||
/// <p>
|
||||
/// Note: When using persistent Jobs whose JobDetail will be kept in the
|
||||
/// database, do not put Spring-managed objects or an ApplicationContext
|
||||
/// reference into the JobDataMap but rather into the SchedulerContext.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <seealso cref="SchedulerFactoryObject.SchedulerContextAsMap" />
|
||||
public virtual IDictionary JobDataAsMap
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentException("Value cannot be null", "value");
|
||||
}
|
||||
|
||||
foreach (DictionaryEntry entry in value)
|
||||
{
|
||||
JobDataMap.Put((string) entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
/// </summary>
|
||||
/// <value>The name of the object in the factory.</value>
|
||||
/// <remarks>
|
||||
/// Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </remarks>
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set { objectName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Spring.Context.IApplicationContext"/> that this
|
||||
/// object runs in.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Normally this call will be used to initialize the object.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Invoked after population of normal object properties but before an
|
||||
/// init callback such as
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// or a custom init-method. Invoked after the setting of any
|
||||
/// <see cref="Spring.Context.IResourceLoaderAware"/>'s
|
||||
/// <see cref="Spring.Context.IResourceLoaderAware.ResourceLoader"/>
|
||||
/// property.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Context.ApplicationContextException">
|
||||
/// In the case of application context initialization errors.
|
||||
/// </exception>
|
||||
/// <exception cref="Spring.Objects.ObjectsException">
|
||||
/// If thrown by any application context methods.
|
||||
/// </exception>
|
||||
/// <exception cref="Spring.Objects.Factory.ObjectInitializationException"/>
|
||||
public virtual IApplicationContext ApplicationContext
|
||||
{
|
||||
set { applicationContext = value; }
|
||||
get { return applicationContext; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the key of an IApplicationContext reference to expose in the JobDataMap,
|
||||
/// for example "applicationContext". Default is none.
|
||||
/// Only applicable when running in a Spring ApplicationContext.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// In case of a QuartzJobObject, the reference will be applied to the Job
|
||||
/// instance as object property. An "applicationContext" attribute will correspond
|
||||
/// to a "setApplicationContext" method in that scenario.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Note that ObjectFactory callback interfaces like IApplicationContextAware
|
||||
/// are not automatically applied to Quartz Job instances, because Quartz
|
||||
/// itself is responsible for the lifecycle of its Jobs.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// <b>Note: When using persistent job stores where JobDetail contents will
|
||||
/// be kept in the database, do not put an IApplicationContext reference into
|
||||
/// the JobDataMap but rather into the SchedulerContext.</b>
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <seealso cref="SchedulerFactoryObject.ApplicationContextSchedulerContextKey" />
|
||||
/// <seealso cref="IApplicationContext" />
|
||||
public virtual string ApplicationContextJobDataKey
|
||||
{
|
||||
set { applicationContextJobDataKey = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
if (Name == null)
|
||||
{
|
||||
Name = objectName;
|
||||
}
|
||||
if (Group == null)
|
||||
{
|
||||
Group = SchedulerConstants.DefaultGroup;
|
||||
}
|
||||
if (applicationContextJobDataKey != null)
|
||||
{
|
||||
if (applicationContext == null)
|
||||
{
|
||||
throw new ArgumentException("JobDetailObject needs to be set up in an IApplicationContext " +
|
||||
"to be able to handle an 'applicationContextJobDataKey'");
|
||||
}
|
||||
JobDataMap.Put(applicationContextJobDataKey, applicationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Common.Logging;
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Quartz ThreadPool adapter that delegates to a Spring-managed
|
||||
/// TaskExecutor instance, specified on SchedulerFactoryObject.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SchedulerFactoryObject.TaskExecutor" />
|
||||
public class LocalTaskExecutorThreadPool : IThreadPool
|
||||
{
|
||||
/// <summary>
|
||||
/// Logger available to subclasses.
|
||||
/// </summary>
|
||||
private readonly ILog logger;
|
||||
|
||||
private ITaskExecutor taskExecutor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalTaskExecutorThreadPool"/> class.
|
||||
/// </summary>
|
||||
public LocalTaskExecutorThreadPool()
|
||||
{
|
||||
logger = LogManager.GetLogger(GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logger instance.
|
||||
/// </summary>
|
||||
protected ILog Logger
|
||||
{
|
||||
get { return logger; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the pool.
|
||||
/// </summary>
|
||||
/// <value>The size of the pool.</value>
|
||||
public virtual int PoolSize
|
||||
{
|
||||
get { return - 1; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inform the <see cref="T:Quartz.Spi.IThreadPool"/> of the Scheduler instance's Id,
|
||||
/// prior to initialize being invoked.
|
||||
/// </summary>
|
||||
public string InstanceId
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inform the <see cref="T:Quartz.Spi.IThreadPool"/> of the Scheduler instance's name,
|
||||
/// prior to initialize being invoked.
|
||||
/// </summary>
|
||||
public string InstanceName
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the QuartzScheduler before the <see cref="T:System.Threading.ThreadPool"/> is
|
||||
/// used, in order to give the it a chance to Initialize.
|
||||
/// </summary>
|
||||
public virtual void Initialize()
|
||||
{
|
||||
// Absolutely needs thread-bound TaskExecutor to Initialize.
|
||||
taskExecutor = SchedulerFactoryObject.ConfigTimeTaskExecutor;
|
||||
if (taskExecutor == null)
|
||||
{
|
||||
throw new SchedulerConfigException("No local TaskExecutor found for configuration - " +
|
||||
"'taskExecutor' property must be set on SchedulerFactoryObject");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the QuartzScheduler to inform the <see cref="T:System.Threading.ThreadPool"/>
|
||||
/// that it should free up all of it's resources because the scheduler is
|
||||
/// shutting down.
|
||||
/// </summary>
|
||||
/// <param name="waitForJobsToComplete"></param>
|
||||
public virtual void Shutdown(bool waitForJobsToComplete)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Execute the given <see cref="T:Quartz.IThreadRunnable"/> in the next
|
||||
/// available <see cref="T:System.Threading.Thread"/>.
|
||||
/// </summary>
|
||||
/// <param name="runnable"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// The implementation of this interface should not throw exceptions unless
|
||||
/// there is a serious problem (i.e. a serious misconfiguration). If there
|
||||
/// are no available threads, rather it should either queue the Runnable, or
|
||||
/// block until a thread is available, depending on the desired strategy.
|
||||
/// </remarks>
|
||||
public virtual bool RunInThread(IThreadRunnable runnable)
|
||||
{
|
||||
if (runnable == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
taskExecutor.Execute(runnable.Run);
|
||||
return true;
|
||||
}
|
||||
catch (TaskRejectedException ex)
|
||||
{
|
||||
logger.Error("Task has been rejected by TaskExecutor", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the number of threads that are currently available in in
|
||||
/// the pool. Useful for determining the number of times
|
||||
/// <see cref="M:Quartz.Spi.IThreadPool.RunInThread(Quartz.IThreadRunnable)"/> can be called before returning
|
||||
/// false.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// the number of currently available threads
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The implementation of this method should block until there is at
|
||||
/// least one available thread.
|
||||
/// </remarks>
|
||||
public virtual int BlockForAvailableThreads()
|
||||
{
|
||||
// The present implementation always returns 1, making Quartz (1.6)
|
||||
// always schedule any tasks that it feels like scheduling.
|
||||
// This could be made smarter for specific TaskExecutors,
|
||||
// for example calling <code>getMaximumPoolSize() - getActiveCount()</code>
|
||||
// on a <code>java.util.concurrent.ThreadPoolExecutor</code>.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Quartz;
|
||||
using Quartz.Impl;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Factory.Config;
|
||||
using Spring.Objects.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// IFactoryObject that exposes a JobDetail object that delegates job execution
|
||||
/// to a specified (static or non-static) method. Avoids the need to implement
|
||||
/// a one-line Quartz Job that just invokes an existing service method.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Derived from ArgumentConverting MethodInvoker to share common properties and behavior
|
||||
/// with MethodInvokingFactoryObject.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Supports both concurrently running jobs and non-currently running
|
||||
/// ones through the "concurrent" property. Jobs created by this
|
||||
/// MethodInvokingJobDetailFactoryObject are by default volatile and durable
|
||||
/// (according to Quartz terminology).
|
||||
/// </p>
|
||||
/// <p><b>NOTE: JobDetails created via this FactoryObject are <i>not</i>
|
||||
/// serializable and thus not suitable for persistent job stores.</b>
|
||||
/// You need to implement your own Quartz Job as a thin wrapper for each case
|
||||
/// where you want a persistent job to delegate to a specific service method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Alef Arendsen</author>
|
||||
/// <seealso cref="Concurrent" />
|
||||
/// <seealso cref="MethodInvokingFactoryObject" />
|
||||
public class MethodInvokingJobDetailFactoryObject : ArgumentConvertingMethodInvoker,
|
||||
IObjectFactoryAware,
|
||||
IFactoryObject,
|
||||
IObjectNameAware,
|
||||
IInitializingObject
|
||||
{
|
||||
private string name;
|
||||
private string group;
|
||||
private bool concurrent = true;
|
||||
private string[] jobListenerNames;
|
||||
private string targetObjectName;
|
||||
private string objectName;
|
||||
private JobDetailImpl jobDetail;
|
||||
private IObjectFactory objectFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MethodInvokingJobDetailFactoryObject"/> class.
|
||||
/// </summary>
|
||||
public MethodInvokingJobDetailFactoryObject()
|
||||
{
|
||||
group = SchedulerConstants.DefaultGroup;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the job.
|
||||
/// Default is the object name of this FactoryObject.
|
||||
/// </summary>
|
||||
/// <seealso cref="Name" />
|
||||
public virtual string Name
|
||||
{
|
||||
set { name = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the group of the job.
|
||||
/// Default is the default group of the Scheduler.
|
||||
/// </summary>
|
||||
/// <seealso cref="Group" />
|
||||
/// <seealso cref="SchedulerConstants.DefaultGroup" />
|
||||
public virtual string Group
|
||||
{
|
||||
set { group = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify whether or not multiple jobs should be run in a concurrent
|
||||
/// fashion. The behavior when one does not want concurrent jobs to be
|
||||
/// executed is realized through adding the <see cref="DisallowConcurrentExecutionAttribute" /> attribute.
|
||||
/// More information on stateful versus stateless jobs can be found
|
||||
/// <a href="http://www.opensymphony.com/quartz/tutorial.html#jobsMore">here</a>.
|
||||
/// <p>
|
||||
/// The default setting is to run jobs concurrently.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
public virtual bool Concurrent
|
||||
{
|
||||
set { concurrent = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the job detail.
|
||||
/// </summary>
|
||||
/// <value>The job detail.</value>
|
||||
protected IJobDetail JobDetail
|
||||
{
|
||||
get { return jobDetail; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a list of JobListener names for this job, referring to
|
||||
/// non-global JobListeners registered with the Scheduler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A JobListener name always refers to the name returned
|
||||
/// by the JobListener implementation.
|
||||
/// </remarks>
|
||||
/// <seealso cref="SchedulerAccessor.JobListeners" />
|
||||
/// <seealso cref="IJobListener.Name" />
|
||||
public virtual string[] JobListenerNames
|
||||
{
|
||||
set { jobListenerNames = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
/// </summary>
|
||||
/// <value>The name of the object in the factory.</value>
|
||||
/// <remarks>
|
||||
/// Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </remarks>
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set { objectName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the target object in the Spring object factory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an alternative to specifying TargetObject
|
||||
/// allowing for non-singleton objects to be invoked. Note that specified
|
||||
/// "TargetObject" and "TargetType" values will
|
||||
/// override the corresponding effect of this "TargetObjectName" setting
|
||||
///(i.e. statically pre-define the object type or even the target object).
|
||||
/// </remarks>
|
||||
public string TargetObjectName
|
||||
{
|
||||
set { targetObjectName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the object factory.
|
||||
/// </summary>
|
||||
/// <value>The object factory.</value>
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set { objectFactory = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance (possibly shared or independent) of the object
|
||||
/// managed by this factory.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An instance (possibly shared or independent) of the object managed by
|
||||
/// this factory.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <note type="caution">
|
||||
/// If this method is being called in the context of an enclosing IoC container and
|
||||
/// returns <see langword="null"/>, the IoC container will consider this factory
|
||||
/// object as not being fully initialized and throw a corresponding (and most
|
||||
/// probably fatal) exception.
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
public virtual object GetObject()
|
||||
{
|
||||
return jobDetail;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <see cref="System.Type"/> of object that this
|
||||
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> creates, or
|
||||
/// <see langword="null"/> if not known in advance.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual Type ObjectType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (targetObjectName != null)
|
||||
{
|
||||
if (objectFactory == null)
|
||||
{
|
||||
throw new InvalidOperationException("ObjectFactory must be set when using 'TargetObjectName'");
|
||||
}
|
||||
return objectFactory.GetType(targetObjectName);
|
||||
}
|
||||
return typeof(IJobDetail);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the object managed by this factory a singleton or a prototype?
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual bool IsSingleton
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
Prepare();
|
||||
|
||||
// Use specific name if given, else fall back to object name.
|
||||
string jobDetailName = name ?? objectName;
|
||||
|
||||
// Consider the concurrent flag to choose between stateful and stateless job.
|
||||
Type jobType = (concurrent ? typeof (MethodInvokingJob) : typeof (StatefulMethodInvokingJob));
|
||||
|
||||
// Build JobDetail instance.
|
||||
jobDetail = new JobDetailImpl(jobDetailName, group, jobType);
|
||||
jobDetail.JobDataMap.Put("methodInvoker", this);
|
||||
jobDetail.Durable = true;
|
||||
|
||||
// job listeners through configuration are no longer supported
|
||||
if (jobListenerNames != null && jobListenerNames.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException("Non-global IJobListeners not supported on Quartz 2 - " +
|
||||
"manually register a Matcher against the Quartz ListenerManager instead");
|
||||
}
|
||||
|
||||
PostProcessJobDetail(jobDetail);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for post-processing the JobDetail to be exposed by this FactoryObject.
|
||||
/// <p>
|
||||
/// The default implementation is empty. Can be overridden in subclasses.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <param name="detail">the JobDetail prepared by this FactoryObject</param>
|
||||
protected virtual void PostProcessJobDetail(IJobDetail detail)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Quartz;
|
||||
|
||||
using Spring.Objects;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple implementation of the Quartz Job interface, applying the
|
||||
/// passed-in JobDataMap and also the SchedulerContext as object property
|
||||
/// values. This is appropriate because a new Job instance will be created
|
||||
/// for each execution. JobDataMap entries will override SchedulerContext
|
||||
/// entries with the same keys.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// For example, let's assume that the JobDataMap contains a key
|
||||
/// "myParam" with value "5": The Job implementation can then expose
|
||||
/// a object property "myParam" of type int to receive such a value,
|
||||
/// i.e. a method "setMyParam(int)". This will also work for complex
|
||||
/// types like business objects etc.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// Note: The QuartzJobObject class itself only implements the standard
|
||||
/// Quartz IJob interface. Let your subclass explicitly implement the
|
||||
/// Quartz IStatefulJob interface to mark your concrete job object as stateful.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="IJobExecutionContext.MergedJobDataMap" />
|
||||
/// <seealso cref="IScheduler.Context" />
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
/// <seealso cref="CronTriggerObject.JobDataAsMap" />
|
||||
/// <seealso cref="SchedulerFactoryObject.SchedulerContextAsMap" />
|
||||
/// <seealso cref="SpringObjectJobFactory" />
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public abstract class QuartzJobObject : IJob
|
||||
{
|
||||
/// <summary>
|
||||
/// This implementation applies the passed-in job data map as object property
|
||||
/// values, and delegates to <code>ExecuteInternal</code> afterwards.
|
||||
/// </summary>
|
||||
/// <seealso cref="ExecuteInternal" />
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
ObjectWrapper bw = new ObjectWrapper(this);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.AddAll(context.Scheduler.Context);
|
||||
pvs.AddAll(context.MergedJobDataMap);
|
||||
bw.SetPropertyValues(pvs, true);
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
throw new JobExecutionException(ex);
|
||||
}
|
||||
ExecuteInternal(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the actual job. The job data map will already have been
|
||||
/// applied as object property values by execute. The contract is
|
||||
/// exactly the same as for the standard Quartz execute method.
|
||||
/// </summary>
|
||||
/// <seealso cref="Execute" />
|
||||
protected abstract void ExecuteInternal(IJobExecutionContext context);
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 System.Threading;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Simpl;
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Subclass of Quartz's SimpleThreadPool that implements Spring's
|
||||
/// TaskExecutor interface and listens to Spring lifecycle callbacks.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SimpleThreadPool" />
|
||||
/// <seealso cref="ITaskExecutor" />
|
||||
/// <seealso cref="SchedulerFactoryObject.TaskExecutor" />
|
||||
public class SimpleThreadPoolTaskExecutor : SimpleThreadPool, ISchedulingTaskExecutor, IInitializingObject, IDisposable
|
||||
{
|
||||
private bool waitForJobsToCompleteOnShutdown = false;
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to wait for running jobs to complete on Shutdown.
|
||||
/// Default is "false".
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [wait for jobs to complete on shutdown]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
/// <seealso cref="SimpleThreadPool.Shutdown(bool)"/>
|
||||
public virtual bool WaitForJobsToCompleteOnShutdown
|
||||
{
|
||||
set { waitForJobsToCompleteOnShutdown = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the specified task.
|
||||
/// </summary>
|
||||
/// <param name="task">The task.</param>
|
||||
public virtual void Execute(ThreadStart task)
|
||||
{
|
||||
if (task == null)
|
||||
{
|
||||
throw new ArgumentException("Runnable must not be null", "task");
|
||||
}
|
||||
if (!RunInThread(new ThreadRunnableDelegate(task)))
|
||||
{
|
||||
throw new SchedulingException("Quartz SimpleThreadPool already shut down");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> This task executor prefers short-lived work units.</summary>
|
||||
public virtual bool PrefersShortLivedTasks
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Shutdown(waitForJobsToCompleteOnShutdown);
|
||||
}
|
||||
|
||||
internal class ThreadRunnableDelegate : IThreadRunnable
|
||||
{
|
||||
private ThreadStart ts;
|
||||
|
||||
|
||||
public ThreadRunnableDelegate(ThreadStart ts)
|
||||
{
|
||||
this.ts = ts;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
ts.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spring.Scheduling
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TaskRejectedException.
|
||||
/// </summary>
|
||||
public class TaskRejectedException : ApplicationException
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright © 2002-2011 the original author or authors.
|
||||
*
|
||||
@@ -16,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
using Quartz.Util;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// JobFactory implementation that supports <see cref="ThreadStart" />
|
||||
/// objects as well as standard Quartz <see cref="IJob" /> instances.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="DelegatingJob" />
|
||||
/// <seealso cref="AdaptJob(object)" />
|
||||
public class AdaptableJobFactory : IJobFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by the scheduler at the time of the trigger firing, in order to
|
||||
/// produce a <see cref="IJob"/> instance on which to call Execute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It should be extremely rare for this method to throw an exception -
|
||||
/// basically only the the case where there is no way at all to instantiate
|
||||
/// and prepare the Job for execution. When the exception is thrown, the
|
||||
/// Scheduler will move all triggers associated with the Job into the
|
||||
/// <see cref="TriggerState.Error"/> state, which will require human
|
||||
/// intervention (e.g. an application restart after fixing whatever
|
||||
/// configuration problem led to the issue wih instantiating the Job.
|
||||
/// </remarks>
|
||||
/// <param name="bundle">The TriggerFiredBundle from which the <see cref="IJobDetail"/>
|
||||
/// and other info relating to the trigger firing can be obtained.</param>
|
||||
/// <param name="scheduler">The scheduler instance.</param>
|
||||
/// <returns>the newly instantiated Job</returns>
|
||||
/// <throws>SchedulerException if there is a problem instantiating the Job.</throws>
|
||||
public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
|
||||
{
|
||||
try
|
||||
{
|
||||
object jobObject = CreateJobInstance(bundle);
|
||||
return AdaptJob(jobObject);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new SchedulerException("Job instantiation failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the the job factory to destroy/cleanup the job if needed.
|
||||
/// </summary>
|
||||
public virtual void ReturnJob(IJob job)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the specified job class.
|
||||
/// <p>
|
||||
/// Can be overridden to post-process the job instance.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <param name="bundle">
|
||||
/// The TriggerFiredBundle from which the JobDetail
|
||||
/// and other info relating to the trigger firing can be obtained.
|
||||
/// </param>
|
||||
/// <returns>The job instance.</returns>
|
||||
protected virtual object CreateJobInstance(TriggerFiredBundle bundle)
|
||||
{
|
||||
return ObjectUtils.InstantiateType<object>(bundle.JobDetail.JobType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapt the given job object to the Quartz Job interface.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default implementation supports straight Quartz Jobs
|
||||
/// as well as Runnables, which get wrapped in a DelegatingJob.
|
||||
/// </remarks>
|
||||
/// <param name="jobObject">
|
||||
/// The original instance of the specified job class.
|
||||
/// </param>
|
||||
/// <returns>The adapted Quartz Job instance.</returns>
|
||||
/// <seealso cref="DelegatingJob" />
|
||||
protected virtual IJob AdaptJob(object jobObject)
|
||||
{
|
||||
if (jobObject is IJob job)
|
||||
{
|
||||
return job;
|
||||
}
|
||||
|
||||
if (jobObject is ThreadStart start)
|
||||
{
|
||||
return new DelegatingJob(start);
|
||||
}
|
||||
|
||||
if (jobObject is IThreadRunnable threadRunnable)
|
||||
{
|
||||
return new DelegatingJob(() => threadRunnable.Run().ConfigureAwait(false).GetAwaiter().GetResult());
|
||||
}
|
||||
|
||||
if (jobObject is Func<Task> func)
|
||||
{
|
||||
return new DelegatingJob(() => func().ConfigureAwait(false).GetAwaiter().GetResult());
|
||||
}
|
||||
|
||||
string message =
|
||||
$"Unable to execute job class [{jobObject.GetType().FullName}]: only [IJob] and [ThreadStart] supported.";
|
||||
throw new ArgumentException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl.Triggers;
|
||||
using Spring.Objects.Factory;
|
||||
@@ -25,69 +24,73 @@ using Spring.Util;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Convenience subclass of Quartz's CronTrigger type, making property based
|
||||
/// usage easier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// CronTrigger itself is already property based but lacks sensible defaults.
|
||||
/// This class uses the Spring object name as job name, the Quartz default group
|
||||
/// ("DEFAULT") as job group, the current time as start time, and indefinite
|
||||
/// repetition, if not specified.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// This class will also register the trigger with the job name and group of
|
||||
/// a given <see cref="JobDetail" />. This allows <see cref="SchedulerFactoryObject" />
|
||||
/// to automatically register a trigger for the corresponding JobDetail,
|
||||
/// instead of registering the JobDetail separately.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <summary>
|
||||
/// Convenience subclass of Quartz's CronTrigger type, making property based
|
||||
/// usage easier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// CronTrigger itself is already property based but lacks sensible defaults.
|
||||
/// This class uses the Spring object name as job name, the Quartz default group
|
||||
/// ("DEFAULT") as job group, the current time as start time, and indefinite
|
||||
/// repetition, if not specified.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// This class will also register the trigger with the job name and group of
|
||||
/// a given <see cref="JobDetail" />. This allows <see cref="SchedulerFactoryObject" />
|
||||
/// to automatically register a trigger for the corresponding JobDetail,
|
||||
/// instead of registering the JobDetail separately.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="ITrigger.Key" />
|
||||
/// <seealso cref="ITrigger.StartTimeUtc" />
|
||||
/// <seealso cref="ITrigger.JobKey" />
|
||||
/// <seealso cref="JobDetail" />
|
||||
/// <seealso cref="SchedulerAccessor.Triggers" />
|
||||
/// <seealso cref="SchedulerAccessor.JobDetails" />
|
||||
public class CronTriggerObject : CronTriggerImpl, IJobDetailAwareTrigger, IObjectNameAware, IInitializingObject
|
||||
{
|
||||
private readonly Constants constants = new Constants(typeof(MisfireInstruction.CronTrigger), typeof(MisfireInstruction));
|
||||
/// <seealso cref="SchedulerAccessor.Triggers" />
|
||||
/// <seealso cref="SchedulerAccessor.JobDetails" />
|
||||
public class CronTriggerObject : CronTriggerImpl, IJobDetailAwareTrigger, IObjectNameAware, IInitializingObject
|
||||
{
|
||||
private readonly Constants constants = new Constants(
|
||||
typeof(MisfireInstruction.CronTrigger),
|
||||
typeof(MisfireInstruction)
|
||||
);
|
||||
|
||||
private IJobDetail jobDetail;
|
||||
private string objectName;
|
||||
private TimeSpan startDelay;
|
||||
private string objectName;
|
||||
private TimeSpan startDelay;
|
||||
|
||||
/// <summary>
|
||||
/// Register objects in the JobDataMap via a given Map.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These objects will be available to this Trigger only,
|
||||
/// in contrast to objects in the JobDetail's data map.
|
||||
/// </remarks>
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
public virtual IDictionary JobDataAsMap
|
||||
{
|
||||
set
|
||||
{
|
||||
foreach (DictionaryEntry entry in value)
|
||||
{
|
||||
JobDataMap.Put((string) entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Register objects in the JobDataMap via a given Map.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These objects will be available to this Trigger only,
|
||||
/// in contrast to objects in the JobDetail's data map.
|
||||
/// </remarks>
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
public virtual IDictionary JobDataAsMap
|
||||
{
|
||||
set
|
||||
{
|
||||
foreach (DictionaryEntry entry in value)
|
||||
{
|
||||
JobDataMap.Put((string) entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the misfire instruction via the name of the corresponding
|
||||
/// constant in the CronTrigger class.
|
||||
/// <summary>
|
||||
/// Set the misfire instruction via the name of the corresponding
|
||||
/// constant in the CronTrigger class.
|
||||
/// Default is <see cref="MisfireInstruction.SmartPolicy" />.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
/// <seealso cref="MisfireInstruction.CronTrigger.FireOnceNow" />
|
||||
/// <seealso cref="MisfireInstruction.CronTrigger.DoNothing" />
|
||||
/// <seealso cref="MisfireInstruction.SmartPolicy" />
|
||||
public virtual string MisfireInstructionName
|
||||
{
|
||||
set { MisfireInstruction = constants.AsNumber(value); }
|
||||
}
|
||||
public virtual string MisfireInstructionName
|
||||
{
|
||||
set => MisfireInstruction = constants.AsNumber(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
@@ -101,25 +104,25 @@ namespace Spring.Scheduling.Quartz
|
||||
/// method or a custom init-method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set { objectName = value; }
|
||||
}
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set => objectName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the JobDetail that this trigger should be associated with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is typically used with a object reference if the JobDetail
|
||||
/// is a Spring-managed object. Alternatively, the trigger can also
|
||||
/// be associated with a job by name and group.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ITrigger.JobKey" />
|
||||
public virtual IJobDetail JobDetail
|
||||
{
|
||||
get { return jobDetail; }
|
||||
set { jobDetail = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Set the JobDetail that this trigger should be associated with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is typically used with a object reference if the JobDetail
|
||||
/// is a Spring-managed object. Alternatively, the trigger can also
|
||||
/// be associated with a job by name and group.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ITrigger.JobKey" />
|
||||
public virtual IJobDetail JobDetail
|
||||
{
|
||||
get => jobDetail;
|
||||
set => jobDetail = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the start delay as <see cref="TimeSpan" />.
|
||||
@@ -136,17 +139,17 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <value>the start delay, as <see cref="TimeSpan" /> object.</value>
|
||||
public TimeSpan StartDelay
|
||||
public TimeSpan StartDelay
|
||||
{
|
||||
set
|
||||
{
|
||||
AssertUtils.State(value >= TimeSpan.Zero, "Start delay cannot be negative.");
|
||||
startDelay = value;
|
||||
}
|
||||
get { return startDelay; }
|
||||
{
|
||||
AssertUtils.State(value >= TimeSpan.Zero, "Start delay cannot be negative.");
|
||||
startDelay = value;
|
||||
}
|
||||
get => startDelay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
@@ -172,31 +175,35 @@ namespace Spring.Scheduling.Quartz
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
if (StartTimeUtc == DateTimeOffset.MinValue)
|
||||
{
|
||||
StartTimeUtc = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
if (StartDelay > TimeSpan.Zero)
|
||||
{
|
||||
StartTimeUtc = DateTime.UtcNow.Add(startDelay);
|
||||
}
|
||||
if (Name == null)
|
||||
{
|
||||
Name = objectName;
|
||||
}
|
||||
if (Group == null)
|
||||
{
|
||||
|
||||
if (Name == null)
|
||||
{
|
||||
Name = objectName;
|
||||
}
|
||||
|
||||
if (Group == null)
|
||||
{
|
||||
Group = SchedulerConstants.DefaultGroup;
|
||||
}
|
||||
if (jobDetail != null)
|
||||
{
|
||||
JobName = jobDetail.Key.Name;
|
||||
JobGroup = jobDetail.Key.Group;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jobDetail != null)
|
||||
{
|
||||
JobName = jobDetail.Key.Name;
|
||||
JobGroup = jobDetail.Key.Group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to map constant names to their values.
|
||||
@@ -222,7 +229,7 @@ namespace Spring.Scheduling.Quartz
|
||||
}
|
||||
|
||||
// not found
|
||||
throw new Exception(string.Format("Unknown field '{0}'", field));
|
||||
throw new Exception($"Unknown field '{field}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,59 +13,50 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Threading;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Quartz;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple Quartz IJob adapter that delegates to a
|
||||
/// <summary>
|
||||
/// Simple Quartz IJob adapter that delegates to a
|
||||
/// given <see cref="ThreadStart" /> instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Typically used in combination with property injection on the
|
||||
/// Runnable instance, receiving parameters from the Quartz JobDataMap
|
||||
/// that way instead of via the JobExecutionContext.
|
||||
/// Typically used in combination with property injection on the
|
||||
/// Runnable instance, receiving parameters from the Quartz JobDataMap
|
||||
/// that way instead of via the JobExecutionContext.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="SpringObjectJobFactory" />
|
||||
/// <seealso cref="IJob.Execute(IJobExecutionContext)" />
|
||||
public class DelegatingJob : IJob
|
||||
{
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="SpringObjectJobFactory" />
|
||||
/// <seealso cref="IJob.Execute(IJobExecutionContext)" />
|
||||
public class DelegatingJob : IJob
|
||||
{
|
||||
private readonly ThreadStart delegateInstance;
|
||||
|
||||
/// <summary>
|
||||
/// Return the wrapped Runnable implementation.
|
||||
/// <summary>
|
||||
/// Create a new DelegatingJob.
|
||||
/// </summary>
|
||||
/// <value>The delegate.</value>
|
||||
public virtual ThreadStart Delegate
|
||||
{
|
||||
get { return delegateInstance; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new DelegatingJob.
|
||||
/// </summary>
|
||||
/// <param name="delegateInstance">
|
||||
/// The Runnable implementation to delegate to.
|
||||
/// </param>
|
||||
/// <param name="delegateInstance">
|
||||
/// The Runnable implementation to delegate to.
|
||||
/// </param>
|
||||
public DelegatingJob(ThreadStart delegateInstance)
|
||||
{
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(delegateInstance, "delegateInstance", "Delegate must not be null");
|
||||
this.delegateInstance = delegateInstance;
|
||||
}
|
||||
this.delegateInstance = delegateInstance;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Delegates execution to the underlying ThreadStart.
|
||||
/// </summary>
|
||||
public virtual void Execute(IJobExecutionContext context)
|
||||
{
|
||||
/// </summary>
|
||||
public virtual Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
delegateInstance.Invoke();
|
||||
}
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Quartz;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to be implemented by Quartz Triggers that are aware
|
||||
/// of the JobDetail object that they are associated with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// SchedulerFactoryObject will auto-detect Triggers that implement this
|
||||
/// interface and register them for the respective JobDetail accordingly.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// The alternative is to configure a Trigger for a Job name and group:
|
||||
/// This involves the need to register the JobDetail object separately
|
||||
/// with SchedulerFactoryObject.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SchedulerAccessor.Triggers" />
|
||||
/// <seealso cref="SchedulerAccessor.JobDetails" />
|
||||
public interface IJobDetailAwareTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the JobDetail that this Trigger is associated with.
|
||||
/// </summary>
|
||||
/// <returns>The associated JobDetail, or <code>null</code> if none</returns>
|
||||
IJobDetail JobDetail { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Quartz;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Callback interface to be implemented by Spring-managed
|
||||
/// Quartz artifacts that need access to the SchedulerContext
|
||||
/// (without having natural access to it).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently only supported for custom JobFactory implementations
|
||||
/// that are passed in via Spring's SchedulerFactoryObject.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="IJobFactory" />
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public interface ISchedulerContextAware
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the SchedulerContext of the current Quartz Scheduler.
|
||||
/// </summary>
|
||||
/// <seealso cref="IScheduler.Context" />
|
||||
SchedulerContext SchedulerContext { set; }
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,14 @@ using System.Threading;
|
||||
|
||||
namespace Spring.Scheduling
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface ITaskExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes this instance.
|
||||
/// </summary>
|
||||
void Execute(ThreadStart runnable);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface ITaskExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes this instance.
|
||||
/// </summary>
|
||||
void Execute(ThreadStart runnable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#region License
|
||||
// /*
|
||||
// * Copyright 2018 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.
|
||||
// */
|
||||
#endregion
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapter interface as Quartz no longer has this interface.
|
||||
/// </summary>
|
||||
public interface IThreadRunnable
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs thread runnable.
|
||||
/// </summary>
|
||||
Task Run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 System.Collections;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Spring.Context;
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Convenience subclass of Quartz' JobDetail class that eases properties based
|
||||
/// usage.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="IJobDetail" /> itself is already a object but lacks
|
||||
/// sensible defaults. This class uses the Spring object name as job name,
|
||||
/// and the Quartz default group ("DEFAULT") as job group if not specified.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="IJobDetail.Key" />
|
||||
/// <seealso cref="SchedulerConstants.DefaultGroup" />
|
||||
public class JobDetailObject : JobDetailImpl, IObjectNameAware, IApplicationContextAware, IInitializingObject
|
||||
{
|
||||
private Type actualJobType;
|
||||
private string objectName;
|
||||
private IApplicationContext applicationContext;
|
||||
private string applicationContextJobDataKey;
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to support any job class, to allow a custom JobFactory
|
||||
/// to adapt the given job class to the Quartz Job interface.
|
||||
/// </summary>
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public override Type JobType
|
||||
{
|
||||
get => actualJobType ?? base.JobType;
|
||||
|
||||
set
|
||||
{
|
||||
if (value != null && !typeof(IJob).IsAssignableFrom(value))
|
||||
{
|
||||
base.JobType = typeof(DelegatingJob);
|
||||
actualJobType = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.JobType = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register objects in the JobDataMap via a given Map.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These objects will be available to this Job only,
|
||||
/// in contrast to objects in the SchedulerContext.
|
||||
/// <p>
|
||||
/// Note: When using persistent Jobs whose JobDetail will be kept in the
|
||||
/// database, do not put Spring-managed objects or an ApplicationContext
|
||||
/// reference into the JobDataMap but rather into the SchedulerContext.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <seealso cref="SchedulerFactoryObject.SchedulerContextAsMap" />
|
||||
public virtual IDictionary JobDataAsMap
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentException("Value cannot be null", "value");
|
||||
}
|
||||
|
||||
foreach (DictionaryEntry entry in value)
|
||||
{
|
||||
JobDataMap.Put((string) entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
/// </summary>
|
||||
/// <value>The name of the object in the factory.</value>
|
||||
/// <remarks>
|
||||
/// Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </remarks>
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set => objectName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Spring.Context.IApplicationContext"/> that this
|
||||
/// object runs in.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Normally this call will be used to initialize the object.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Invoked after population of normal object properties but before an
|
||||
/// init callback such as
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// or a custom init-method. Invoked after the setting of any
|
||||
/// <see cref="Spring.Context.IResourceLoaderAware"/>'s
|
||||
/// <see cref="Spring.Context.IResourceLoaderAware.ResourceLoader"/>
|
||||
/// property.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Context.ApplicationContextException">
|
||||
/// In the case of application context initialization errors.
|
||||
/// </exception>
|
||||
/// <exception cref="Spring.Objects.ObjectsException">
|
||||
/// If thrown by any application context methods.
|
||||
/// </exception>
|
||||
/// <exception cref="Spring.Objects.Factory.ObjectInitializationException"/>
|
||||
public virtual IApplicationContext ApplicationContext
|
||||
{
|
||||
set => applicationContext = value;
|
||||
get => applicationContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the key of an IApplicationContext reference to expose in the JobDataMap,
|
||||
/// for example "applicationContext". Default is none.
|
||||
/// Only applicable when running in a Spring ApplicationContext.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// In case of a QuartzJobObject, the reference will be applied to the Job
|
||||
/// instance as object property. An "applicationContext" attribute will correspond
|
||||
/// to a "setApplicationContext" method in that scenario.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Note that ObjectFactory callback interfaces like IApplicationContextAware
|
||||
/// are not automatically applied to Quartz Job instances, because Quartz
|
||||
/// itself is responsible for the lifecycle of its Jobs.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// <b>Note: When using persistent job stores where JobDetail contents will
|
||||
/// be kept in the database, do not put an IApplicationContext reference into
|
||||
/// the JobDataMap but rather into the SchedulerContext.</b>
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <seealso cref="SchedulerFactoryObject.ApplicationContextSchedulerContextKey" />
|
||||
/// <seealso cref="IApplicationContext" />
|
||||
public virtual string ApplicationContextJobDataKey
|
||||
{
|
||||
set => applicationContextJobDataKey = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
if (Name == null)
|
||||
{
|
||||
Name = objectName;
|
||||
}
|
||||
|
||||
if (Group == null)
|
||||
{
|
||||
Group = SchedulerConstants.DefaultGroup;
|
||||
}
|
||||
|
||||
if (applicationContextJobDataKey != null)
|
||||
{
|
||||
if (applicationContext == null)
|
||||
{
|
||||
throw new ArgumentException("JobDetailObject needs to be set up in an IApplicationContext " +
|
||||
"to be able to handle an 'applicationContextJobDataKey'");
|
||||
}
|
||||
|
||||
JobDataMap.Put(applicationContextJobDataKey, applicationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using Spring.Objects.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
@@ -35,12 +34,9 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <param name="methodInvoker">the MethodInvoker used for reflective invocation</param>
|
||||
/// <param name="cause">the root cause (as thrown from the target method)</param>
|
||||
public JobMethodInvocationFailedException(MethodInvoker methodInvoker, Exception cause) :
|
||||
base("Invocation of method '" + methodInvoker.TargetMethod +
|
||||
"' on target class [" + methodInvoker.TargetType + "] failed", cause)
|
||||
base("Invocation of method '" + methodInvoker.TargetMethod +
|
||||
"' on target class [" + methodInvoker.TargetType + "] failed", cause)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,10 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Data.Common;
|
||||
using Quartz;
|
||||
using Quartz.Impl.AdoJobStore;
|
||||
using Quartz.Util;
|
||||
|
||||
using Spring.Data.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
@@ -48,7 +48,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="DBConnectionManager.AddConnectionProvider" />
|
||||
/// <seealso cref="SchedulerFactoryObject.DbProvider" />
|
||||
/// </summary>
|
||||
public const string TX_DATA_SOURCE_PREFIX = "springTxDataSource.";
|
||||
public const string TxDataSourcePrefix = "springTxDataSource.";
|
||||
|
||||
private Data.Common.IDbProvider dbProvider;
|
||||
|
||||
@@ -58,12 +58,12 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The name of the instance.</value>
|
||||
public override string InstanceName
|
||||
{
|
||||
get { return base.InstanceName; }
|
||||
get => base.InstanceName;
|
||||
set
|
||||
{
|
||||
// use to catch property setting
|
||||
base.InstanceName = value;
|
||||
DataSource = TX_DATA_SOURCE_PREFIX + InstanceName;
|
||||
DataSource = TxDataSourcePrefix + InstanceName;
|
||||
// Register transactional ConnectionProvider for Quartz.
|
||||
// Absolutely needs thread-bound DataSource to initialize.
|
||||
dbProvider = SchedulerFactoryObject.ConfigTimeDbProvider;
|
||||
@@ -72,10 +72,10 @@ namespace Spring.Scheduling.Quartz
|
||||
throw new SchedulerConfigException(
|
||||
"No db provider found for configuration - " +
|
||||
"'DbProvider' property must be set on SchedulerFactoryObject");
|
||||
}
|
||||
DBConnectionManager.Instance.AddConnectionProvider(
|
||||
TX_DATA_SOURCE_PREFIX + InstanceName, new SpringDbProviderAdapter(dbProvider));
|
||||
}
|
||||
|
||||
DBConnectionManager.Instance.AddConnectionProvider(
|
||||
TxDataSourcePrefix + InstanceName, new SpringDbProviderAdapter(dbProvider));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Spring.Scheduling.Quartz
|
||||
protected override ConnectionAndTransactionHolder GetNonManagedTXConnection()
|
||||
{
|
||||
ConnectionTxPair pair = ConnectionUtils.DoGetConnection(dbProvider);
|
||||
return new ConnectionAndTransactionHolder(pair.Connection, pair.Transaction);
|
||||
return new ConnectionAndTransactionHolder((DbConnection) pair.Connection, (DbTransaction) pair.Transaction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -99,4 +99,4 @@ namespace Spring.Scheduling.Quartz
|
||||
ConnectionUtils.DisposeConnection(connectionAndTransactionHolder.Connection, dbProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 System.Threading.Tasks;
|
||||
using Common.Logging;
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Quartz ThreadPool adapter that delegates to a Spring-managed
|
||||
/// TaskExecutor instance, specified on SchedulerFactoryObject.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SchedulerFactoryObject.TaskExecutor" />
|
||||
public class LocalTaskExecutorThreadPool : IThreadPool
|
||||
{
|
||||
private ITaskExecutor taskExecutor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalTaskExecutorThreadPool"/> class.
|
||||
/// </summary>
|
||||
public LocalTaskExecutorThreadPool()
|
||||
{
|
||||
Logger = LogManager.GetLogger(GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logger instance.
|
||||
/// </summary>
|
||||
protected ILog Logger { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual int PoolSize => -1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string InstanceId
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string InstanceName
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Initialize()
|
||||
{
|
||||
// Absolutely needs thread-bound TaskExecutor to Initialize.
|
||||
taskExecutor = SchedulerFactoryObject.ConfigTimeTaskExecutor;
|
||||
if (taskExecutor == null)
|
||||
{
|
||||
throw new SchedulerConfigException("No local TaskExecutor found for configuration - " +
|
||||
"'taskExecutor' property must be set on SchedulerFactoryObject");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Shutdown(bool waitForJobsToComplete)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool RunInThread(Func<Task> runnable)
|
||||
{
|
||||
if (runnable == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
taskExecutor.Execute(() => runnable().ConfigureAwait(false).GetAwaiter().GetResult());
|
||||
return true;
|
||||
}
|
||||
catch (TaskRejectedException ex)
|
||||
{
|
||||
Logger.Error("Task has been rejected by TaskExecutor", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual int BlockForAvailableThreads()
|
||||
{
|
||||
// The present implementation always returns 1, making Quartz (1.6)
|
||||
// always schedule any tasks that it feels like scheduling.
|
||||
// This could be made smarter for specific TaskExecutors,
|
||||
// for example calling <code>getMaximumPoolSize() - getActiveCount()</code>
|
||||
// on a <code>java.util.concurrent.ThreadPoolExecutor</code>.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Common.Logging;
|
||||
|
||||
using Quartz;
|
||||
|
||||
using Spring.Objects.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
@@ -42,28 +40,23 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentException("Method invoker cannot be null", "value");
|
||||
}
|
||||
methodInvoker = value;
|
||||
methodInvoker = value ?? throw new ArgumentException("Method invoker cannot be null", nameof(value));
|
||||
errorMessage =
|
||||
string.Format("Could not invoke method '{0}' on target object [{1}]", methodInvoker.TargetMethod,
|
||||
methodInvoker.TargetObject);
|
||||
$"Could not invoke method '{methodInvoker.TargetMethod}' on target object [{methodInvoker.TargetObject}]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invoke the method via the MethodInvoker.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
protected override void ExecuteInternal(IJobExecutionContext context)
|
||||
protected override Task ExecuteInternal(IJobExecutionContext context)
|
||||
{
|
||||
if (methodInvoker == null)
|
||||
{
|
||||
throw new JobExecutionException("Could not execute job when method invoker is null");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
context.Result = methodInvoker.Invoke();
|
||||
@@ -76,15 +69,17 @@ namespace Spring.Scheduling.Quartz
|
||||
// -> JobExecutionException, to be logged at info level by Quartz
|
||||
throw ex.GetBaseException();
|
||||
}
|
||||
|
||||
// -> "unhandled exception", to be logged at error level by Quartz
|
||||
throw new JobMethodInvocationFailedException(methodInvoker, ex.GetBaseException());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// -> "unhandled exception", to be logged at error level by Quartz
|
||||
throw new JobMethodInvocationFailedException(methodInvoker, ex.GetBaseException());
|
||||
throw new JobMethodInvocationFailedException(methodInvoker, ex.GetBaseException());
|
||||
}
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 Quartz;
|
||||
using Quartz.Impl;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Factory.Config;
|
||||
using Spring.Objects.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// IFactoryObject that exposes a JobDetail object that delegates job execution
|
||||
/// to a specified (static or non-static) method. Avoids the need to implement
|
||||
/// a one-line Quartz Job that just invokes an existing service method.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Derived from ArgumentConverting MethodInvoker to share common properties and behavior
|
||||
/// with MethodInvokingFactoryObject.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Supports both concurrently running jobs and non-currently running
|
||||
/// ones through the "concurrent" property. Jobs created by this
|
||||
/// MethodInvokingJobDetailFactoryObject are by default volatile and durable
|
||||
/// (according to Quartz terminology).
|
||||
/// </p>
|
||||
/// <p><b>NOTE: JobDetails created via this FactoryObject are <i>not</i>
|
||||
/// serializable and thus not suitable for persistent job stores.</b>
|
||||
/// You need to implement your own Quartz Job as a thin wrapper for each case
|
||||
/// where you want a persistent job to delegate to a specific service method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Alef Arendsen</author>
|
||||
/// <seealso cref="Concurrent" />
|
||||
/// <seealso cref="MethodInvokingFactoryObject" />
|
||||
public class MethodInvokingJobDetailFactoryObject : ArgumentConvertingMethodInvoker,
|
||||
IObjectFactoryAware,
|
||||
IFactoryObject,
|
||||
IObjectNameAware,
|
||||
IInitializingObject
|
||||
{
|
||||
private string name;
|
||||
private string group;
|
||||
private bool concurrent = true;
|
||||
private string[] jobListenerNames;
|
||||
private string targetObjectName;
|
||||
private string objectName;
|
||||
private JobDetailImpl jobDetail;
|
||||
private IObjectFactory objectFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MethodInvokingJobDetailFactoryObject"/> class.
|
||||
/// </summary>
|
||||
public MethodInvokingJobDetailFactoryObject()
|
||||
{
|
||||
group = SchedulerConstants.DefaultGroup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the job.
|
||||
/// Default is the object name of this FactoryObject.
|
||||
/// </summary>
|
||||
/// <seealso cref="Name" />
|
||||
public virtual string Name
|
||||
{
|
||||
set => name = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the group of the job.
|
||||
/// Default is the default group of the Scheduler.
|
||||
/// </summary>
|
||||
/// <seealso cref="Group" />
|
||||
/// <seealso cref="SchedulerConstants.DefaultGroup" />
|
||||
public virtual string Group
|
||||
{
|
||||
set => group = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify whether or not multiple jobs should be run in a concurrent
|
||||
/// fashion. The behavior when one does not want concurrent jobs to be
|
||||
/// executed is realized through adding the <see cref="DisallowConcurrentExecutionAttribute" /> attribute.
|
||||
/// More information on stateful versus stateless jobs can be found
|
||||
/// <a href="http://www.opensymphony.com/quartz/tutorial.html#jobsMore">here</a>.
|
||||
/// <p>
|
||||
/// The default setting is to run jobs concurrently.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
public virtual bool Concurrent
|
||||
{
|
||||
set => concurrent = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the job detail.
|
||||
/// </summary>
|
||||
/// <value>The job detail.</value>
|
||||
protected IJobDetail JobDetail => jobDetail;
|
||||
|
||||
/// <summary>
|
||||
/// Set a list of JobListener names for this job, referring to
|
||||
/// non-global JobListeners registered with the Scheduler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A JobListener name always refers to the name returned
|
||||
/// by the JobListener implementation.
|
||||
/// </remarks>
|
||||
/// <seealso cref="SchedulerAccessor.JobListeners" />
|
||||
/// <seealso cref="IJobListener.Name" />
|
||||
public virtual string[] JobListenerNames
|
||||
{
|
||||
set => jobListenerNames = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
/// </summary>
|
||||
/// <value>The name of the object in the factory.</value>
|
||||
/// <remarks>
|
||||
/// Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </remarks>
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set => objectName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the target object in the Spring object factory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an alternative to specifying TargetObject
|
||||
/// allowing for non-singleton objects to be invoked. Note that specified
|
||||
/// "TargetObject" and "TargetType" values will
|
||||
/// override the corresponding effect of this "TargetObjectName" setting
|
||||
///(i.e. statically pre-define the object type or even the target object).
|
||||
/// </remarks>
|
||||
public string TargetObjectName
|
||||
{
|
||||
set => targetObjectName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the object factory.
|
||||
/// </summary>
|
||||
/// <value>The object factory.</value>
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set => objectFactory = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance (possibly shared or independent) of the object
|
||||
/// managed by this factory.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An instance (possibly shared or independent) of the object managed by
|
||||
/// this factory.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <note type="caution">
|
||||
/// If this method is being called in the context of an enclosing IoC container and
|
||||
/// returns <see langword="null"/>, the IoC container will consider this factory
|
||||
/// object as not being fully initialized and throw a corresponding (and most
|
||||
/// probably fatal) exception.
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
public virtual object GetObject()
|
||||
{
|
||||
return jobDetail;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <see cref="System.Type"/> of object that this
|
||||
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> creates, or
|
||||
/// <see langword="null"/> if not known in advance.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual Type ObjectType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (targetObjectName != null)
|
||||
{
|
||||
if (objectFactory == null)
|
||||
{
|
||||
throw new InvalidOperationException("ObjectFactory must be set when using 'TargetObjectName'");
|
||||
}
|
||||
|
||||
return objectFactory.GetType(targetObjectName);
|
||||
}
|
||||
|
||||
return typeof(IJobDetail);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the object managed by this factory a singleton or a prototype?
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual bool IsSingleton => true;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
Prepare();
|
||||
|
||||
// Use specific name if given, else fall back to object name.
|
||||
string jobDetailName = name ?? objectName;
|
||||
|
||||
// Consider the concurrent flag to choose between stateful and stateless job.
|
||||
Type jobType = (concurrent ? typeof(MethodInvokingJob) : typeof(StatefulMethodInvokingJob));
|
||||
|
||||
// Build JobDetail instance.
|
||||
jobDetail = new JobDetailImpl(jobDetailName, group, jobType);
|
||||
jobDetail.JobDataMap.Put("methodInvoker", this);
|
||||
jobDetail.Durable = true;
|
||||
|
||||
// job listeners through configuration are no longer supported
|
||||
if (jobListenerNames != null && jobListenerNames.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException("Non-global IJobListeners not supported on Quartz 2 - " +
|
||||
"manually register a Matcher against the Quartz ListenerManager instead");
|
||||
}
|
||||
|
||||
PostProcessJobDetail(jobDetail);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for post-processing the JobDetail to be exposed by this FactoryObject.
|
||||
/// <p>
|
||||
/// The default implementation is empty. Can be overridden in subclasses.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <param name="detail">the JobDetail prepared by this FactoryObject</param>
|
||||
protected virtual void PostProcessJobDetail(IJobDetail detail)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Common.Logging;
|
||||
|
||||
using Quartz;
|
||||
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Support;
|
||||
|
||||
@@ -34,19 +32,6 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Derives from ArgumentConvertingMethodInvoker, inheriting common
|
||||
/// configuration properties from MethodInvoker.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// Useful to generically encapsulate a method invocation as timer task for
|
||||
/// <code>java.util.Timer</code>, in combination with a DelegatingTimerTask adapter.
|
||||
/// Can also be used with JDK 1.5's <code>java.util.concurrent.Executor</code>
|
||||
/// abstraction, which works with plain Runnables.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Extended by Spring's MethodInvokingTimerTaskFactoryObject adapter
|
||||
/// for <code>TimerTask</code>. Note that you can populate a
|
||||
/// ScheduledTimerTask object with a plain MethodInvokingRunnable instance
|
||||
/// as well, which will automatically get wrapped with a DelegatingTimerTask.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="MethodInvoker" />
|
||||
@@ -69,19 +54,14 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// Logger instance.
|
||||
/// </summary>
|
||||
protected ILog Logger
|
||||
{
|
||||
get { return logger; }
|
||||
}
|
||||
protected ILog Logger => logger;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the invocation failure message.
|
||||
/// </summary>
|
||||
/// <value>The invocation failure message.</value>
|
||||
protected virtual string InvocationFailureMessage
|
||||
{
|
||||
get { return string.Format("Invocation of method '{0}' on target object [{1}] failed", TargetMethod, TargetObject); }
|
||||
}
|
||||
protected virtual string InvocationFailureMessage =>
|
||||
$"Invocation of method '{TargetMethod}' on target object [{TargetObject}] failed";
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
@@ -118,7 +98,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// This method has to be implemented in order that starting of the thread causes the object's
|
||||
/// run method to be called in that separately executing thread.
|
||||
/// </summary>
|
||||
public virtual void Run()
|
||||
public virtual Task Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -134,6 +114,8 @@ namespace Spring.Scheduling.Quartz
|
||||
logger.Error(InvocationFailureMessage, ex);
|
||||
// Do not throw exception, else the main loop of the Timer will stop!
|
||||
}
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.Threading.Tasks;
|
||||
using Quartz;
|
||||
using Spring.Objects;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple implementation of the Quartz Job interface, applying the
|
||||
/// passed-in JobDataMap and also the SchedulerContext as object property
|
||||
/// values. This is appropriate because a new Job instance will be created
|
||||
/// for each execution. JobDataMap entries will override SchedulerContext
|
||||
/// entries with the same keys.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// For example, let's assume that the JobDataMap contains a key
|
||||
/// "myParam" with value "5": The Job implementation can then expose
|
||||
/// a object property "myParam" of type int to receive such a value,
|
||||
/// i.e. a method "setMyParam(int)". This will also work for complex
|
||||
/// types like business objects etc.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// Note: The QuartzJobObject class itself only implements the standard
|
||||
/// Quartz IJob interface. Let your subclass explicitly implement the
|
||||
/// Quartz IStatefulJob interface to mark your concrete job object as stateful.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="IJobExecutionContext.MergedJobDataMap" />
|
||||
/// <seealso cref="IScheduler.Context" />
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
/// <seealso cref="CronTriggerObject.JobDataAsMap" />
|
||||
/// <seealso cref="SchedulerFactoryObject.SchedulerContextAsMap" />
|
||||
/// <seealso cref="SpringObjectJobFactory" />
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public abstract class QuartzJobObject : IJob
|
||||
{
|
||||
/// <summary>
|
||||
/// This implementation applies the passed-in job data map as object property
|
||||
/// values, and delegates to <code>ExecuteInternal</code> afterwards.
|
||||
/// </summary>
|
||||
/// <seealso cref="ExecuteInternal" />
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
ObjectWrapper bw = new ObjectWrapper(this);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.AddAll(context.Scheduler.Context);
|
||||
pvs.AddAll(context.MergedJobDataMap);
|
||||
bw.SetPropertyValues(pvs, true);
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
throw new JobExecutionException(ex);
|
||||
}
|
||||
|
||||
return ExecuteInternal(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the actual job. The job data map will already have been
|
||||
/// applied as object property values by execute. The contract is
|
||||
/// exactly the same as for the standard Quartz execute method.
|
||||
/// </summary>
|
||||
/// <seealso cref="Execute" />
|
||||
protected abstract Task ExecuteInternal(IJobExecutionContext context);
|
||||
}
|
||||
}
|
||||
@@ -14,16 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Common.Logging;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Simpl;
|
||||
using Quartz.Xml;
|
||||
|
||||
using Spring.Collections;
|
||||
using Spring.Context;
|
||||
using Spring.Core.IO;
|
||||
@@ -48,6 +46,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Logger instance.
|
||||
/// </summary>
|
||||
private readonly ILog logger;
|
||||
|
||||
private bool overwriteExistingJobs;
|
||||
|
||||
private string[] jobSchedulingDataLocations;
|
||||
@@ -63,6 +62,7 @@ namespace Spring.Scheduling.Quartz
|
||||
private ITriggerListener[] triggerListeners;
|
||||
|
||||
private IPlatformTransactionManager transactionManager;
|
||||
|
||||
/// <summary>
|
||||
/// Resource loader instance for sub-classes
|
||||
/// </summary>
|
||||
@@ -83,10 +83,9 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public virtual bool OverwriteExistingJobs
|
||||
{
|
||||
set { overwriteExistingJobs = value; }
|
||||
set => overwriteExistingJobs = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the locations of Quartz job definition XML files that follow the
|
||||
/// "job_scheduling_data_1_5" XSD. Can be specified to automatically
|
||||
@@ -96,7 +95,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="XMLSchedulingDataProcessor" />
|
||||
public virtual string[] JobSchedulingDataLocations
|
||||
{
|
||||
set { jobSchedulingDataLocations = value; }
|
||||
set => jobSchedulingDataLocations = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -108,7 +107,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="XMLSchedulingDataProcessor" />
|
||||
public virtual string JobSchedulingDataLocation
|
||||
{
|
||||
set { jobSchedulingDataLocations = new string[] {value}; }
|
||||
set => jobSchedulingDataLocations = new string[] {value};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,12 +124,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="ITrigger.JobKey" />
|
||||
public virtual IJobDetail[] JobDetails
|
||||
{
|
||||
set
|
||||
{
|
||||
// Use modifiable ArrayList here, to allow for further adding of
|
||||
// JobDetail objects during autodetection of JobDetailAwareTriggers.
|
||||
jobDetails = new List<IJobDetail>(value);
|
||||
}
|
||||
set => jobDetails = new List<IJobDetail>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -142,7 +136,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="ITrigger.CalendarName" />
|
||||
public virtual IDictionary Calendars
|
||||
{
|
||||
set { calendars = value; }
|
||||
set => calendars = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -162,7 +156,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="SimpleTriggerObject" />
|
||||
public virtual ITrigger[] Triggers
|
||||
{
|
||||
set { triggers = new ArrayList(value); }
|
||||
set => triggers = new ArrayList(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -170,7 +164,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public virtual ISchedulerListener[] SchedulerListeners
|
||||
{
|
||||
set { schedulerListeners = value; }
|
||||
set => schedulerListeners = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -179,7 +173,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public virtual IJobListener[] GlobalJobListeners
|
||||
{
|
||||
set { globalJobListeners = value; }
|
||||
set => globalJobListeners = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -190,20 +184,18 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="IJobListener.Name" />
|
||||
public virtual IJobListener[] JobListeners
|
||||
{
|
||||
set { jobListeners = value; }
|
||||
set => jobListeners = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specify global Quartz TriggerListeners to be registered with the Scheduler.
|
||||
/// Such TriggerListeners will apply to all Triggers in the Scheduler.
|
||||
/// </summary>
|
||||
public virtual ITriggerListener[] GlobalTriggerListeners
|
||||
{
|
||||
set { globalTriggerListeners = value; }
|
||||
set => globalTriggerListeners = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specify named Quartz TriggerListeners to be registered with the Scheduler.
|
||||
/// Such TriggerListeners will only apply to Triggers that explicitly activate
|
||||
@@ -212,10 +204,9 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="ITriggerListener.Name" />
|
||||
public virtual ITriggerListener[] TriggerListeners
|
||||
{
|
||||
set { triggerListeners = value; }
|
||||
set => triggerListeners = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the transaction manager to be used for registering jobs and triggers
|
||||
/// that are defined by this SchedulerFactoryObject. Default is none; setting
|
||||
@@ -223,7 +214,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public virtual IPlatformTransactionManager TransactionManager
|
||||
{
|
||||
set { transactionManager = value; }
|
||||
set => transactionManager = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -250,30 +241,28 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// Logger instance.
|
||||
/// </summary>
|
||||
protected ILog Logger
|
||||
{
|
||||
get { return logger; }
|
||||
}
|
||||
protected ILog Logger => logger;
|
||||
|
||||
/// <summary>
|
||||
/// Register jobs and triggers (within a transaction, if possible).
|
||||
/// </summary>
|
||||
protected virtual void RegisterJobsAndTriggers()
|
||||
protected virtual async Task RegisterJobsAndTriggers()
|
||||
{
|
||||
ITransactionStatus transactionStatus = null;
|
||||
if (transactionManager != null)
|
||||
{
|
||||
transactionStatus = transactionManager.GetTransaction(new DefaultTransactionDefinition());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (jobSchedulingDataLocations != null)
|
||||
{
|
||||
XMLSchedulingDataProcessor dataProcessor = new XMLSchedulingDataProcessor(new SimpleTypeLoadHelper());
|
||||
var dataProcessor = new XMLSchedulingDataProcessor(new SimpleTypeLoadHelper());
|
||||
dataProcessor.OverWriteExistingData = overwriteExistingJobs;
|
||||
foreach (string location in jobSchedulingDataLocations)
|
||||
{
|
||||
dataProcessor.ProcessFileAndScheduleJobs(location, GetScheduler());
|
||||
await dataProcessor.ProcessFileAndScheduleJobs(location, GetScheduler()).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +271,7 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
foreach (IJobDetail jobDetail in jobDetails)
|
||||
{
|
||||
AddJobToScheduler(jobDetail);
|
||||
await AddJobToScheduler(jobDetail).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -298,7 +287,7 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
string calendarName = (string) entry.Key;
|
||||
ICalendar calendar = (ICalendar) entry.Value;
|
||||
GetScheduler().AddCalendar(calendarName, calendar, true, true);
|
||||
await GetScheduler().AddCalendar(calendarName, calendar, true, true).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,11 +296,10 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
foreach (ITrigger trigger in triggers)
|
||||
{
|
||||
AddTriggerToScheduler(trigger);
|
||||
await AddTriggerToScheduler(trigger).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (transactionStatus != null)
|
||||
@@ -326,10 +314,12 @@ namespace Spring.Scheduling.Quartz
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (ex is SchedulerException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new SchedulerException("Registration of jobs and triggers failed: " + ex.Message);
|
||||
}
|
||||
|
||||
@@ -345,17 +335,16 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
/// <param name="jobDetail">the job to add</param>
|
||||
/// <returns><code>true</code> if the job was actually added, <code>false</code> if it already existed before</returns>
|
||||
private bool AddJobToScheduler(IJobDetail jobDetail)
|
||||
private async Task<bool> AddJobToScheduler(IJobDetail jobDetail)
|
||||
{
|
||||
if (overwriteExistingJobs || GetScheduler().GetJobDetail(jobDetail.Key) == null)
|
||||
if (overwriteExistingJobs
|
||||
|| await GetScheduler().GetJobDetail(jobDetail.Key).ConfigureAwait(false) == null)
|
||||
{
|
||||
GetScheduler().AddJob(jobDetail, true, true);
|
||||
await GetScheduler().AddJob(jobDetail, true, true).ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -364,45 +353,48 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
/// <param name="trigger">the trigger to add</param>
|
||||
/// <returns><code>true</code> if the trigger was actually added, <code>false</code> if it already existed before</returns>
|
||||
private bool AddTriggerToScheduler(ITrigger trigger)
|
||||
private async Task<bool> AddTriggerToScheduler(ITrigger trigger)
|
||||
{
|
||||
bool triggerExists = (GetScheduler().GetTrigger(trigger.Key) != null);
|
||||
if (!triggerExists || this.overwriteExistingJobs)
|
||||
bool triggerExists = await GetScheduler().GetTrigger(trigger.Key).ConfigureAwait(false) != null;
|
||||
if (!triggerExists || overwriteExistingJobs)
|
||||
{
|
||||
// Check if the Trigger is aware of an associated JobDetail.
|
||||
if (trigger is IJobDetailAwareTrigger)
|
||||
if (trigger is IJobDetailAwareTrigger awareTrigger)
|
||||
{
|
||||
IJobDetail jobDetail = ((IJobDetailAwareTrigger) trigger).JobDetail;
|
||||
IJobDetail jobDetail = awareTrigger.JobDetail;
|
||||
// Automatically register the JobDetail too.
|
||||
if (!jobDetails.Contains(jobDetail) && AddJobToScheduler(jobDetail))
|
||||
if (!jobDetails.Contains(jobDetail)
|
||||
&& await AddJobToScheduler(jobDetail).ConfigureAwait(false))
|
||||
{
|
||||
jobDetails.Add(jobDetail);
|
||||
}
|
||||
}
|
||||
|
||||
if (!triggerExists)
|
||||
{
|
||||
try
|
||||
{
|
||||
GetScheduler().ScheduleJob(trigger);
|
||||
await GetScheduler().ScheduleJob(trigger).ConfigureAwait(false);
|
||||
}
|
||||
catch (ObjectAlreadyExistsException ex)
|
||||
{
|
||||
if (logger.IsDebugEnabled)
|
||||
{
|
||||
logger.Debug(
|
||||
"Unexpectedly found existing trigger, assumably due to cluster race condition: " +
|
||||
ex.Message + " - can safely be ignored");
|
||||
$"Unexpectedly found existing trigger, assumably due to cluster race condition: {ex.Message} - can safely be ignored");
|
||||
}
|
||||
|
||||
if (overwriteExistingJobs)
|
||||
{
|
||||
GetScheduler().RescheduleJob(trigger.Key, trigger);
|
||||
await GetScheduler().RescheduleJob(trigger.Key, trigger).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetScheduler().RescheduleJob(trigger.Key, trigger);
|
||||
await GetScheduler().RescheduleJob(trigger.Key, trigger).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -411,7 +403,6 @@ namespace Spring.Scheduling.Quartz
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Register all specified listeners with the Scheduler.
|
||||
/// </summary>
|
||||
@@ -424,6 +415,7 @@ namespace Spring.Scheduling.Quartz
|
||||
GetScheduler().ListenerManager.AddSchedulerListener(schedulerListeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (globalJobListeners != null)
|
||||
{
|
||||
foreach (IJobListener jobListener in globalJobListeners)
|
||||
@@ -431,11 +423,13 @@ namespace Spring.Scheduling.Quartz
|
||||
GetScheduler().ListenerManager.AddJobListener(jobListener);
|
||||
}
|
||||
}
|
||||
|
||||
if (jobListeners != null && jobListeners.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException("Non-global JobListeners not supported on Quartz 2 - " +
|
||||
"manually register a Matcher against the Quartz ListenerManager instead");
|
||||
throw new InvalidOperationException("Non-global JobListeners not supported on Quartz 2 - " +
|
||||
"manually register a Matcher against the Quartz ListenerManager instead");
|
||||
}
|
||||
|
||||
if (globalTriggerListeners != null)
|
||||
{
|
||||
foreach (ITriggerListener triggerListener in globalTriggerListeners)
|
||||
@@ -443,10 +437,11 @@ namespace Spring.Scheduling.Quartz
|
||||
GetScheduler().ListenerManager.AddTriggerListener(triggerListener);
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerListeners != null && triggerListeners.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException("Non-global TriggerListeners not supported on Quartz 2 - " +
|
||||
"manually register a Matcher against the Quartz ListenerManager instead");
|
||||
"manually register a Matcher against the Quartz ListenerManager instead");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
@@ -50,7 +48,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </remarks>
|
||||
public string SchedulerName
|
||||
{
|
||||
set { schedulerName = value; }
|
||||
set => schedulerName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,7 +56,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
protected IScheduler Scheduler
|
||||
{
|
||||
set { scheduler = value; }
|
||||
set => scheduler = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -75,10 +73,9 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set { objectFactory = value; }
|
||||
set => objectFactory = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
@@ -118,8 +115,9 @@ namespace Spring.Scheduling.Quartz
|
||||
throw new InvalidOperationException("No Scheduler specified");
|
||||
}
|
||||
}
|
||||
|
||||
RegisterListeners();
|
||||
RegisterJobsAndTriggers();
|
||||
RegisterJobsAndTriggers().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -129,26 +127,27 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <returns></returns>
|
||||
protected virtual IScheduler FindScheduler(string schedulerName)
|
||||
{
|
||||
if (objectFactory is IListableObjectFactory)
|
||||
if (objectFactory is IListableObjectFactory lbf)
|
||||
{
|
||||
IListableObjectFactory lbf = (IListableObjectFactory) objectFactory;
|
||||
IEnumerable<string> objectNames = lbf.GetObjectNamesForType(typeof(IScheduler));
|
||||
var objectNames = lbf.GetObjectNamesForType(typeof(IScheduler));
|
||||
foreach (string objectName in objectNames)
|
||||
{
|
||||
IScheduler schedulerObject = (IScheduler)lbf.GetObject(objectName);
|
||||
IScheduler schedulerObject = (IScheduler) lbf.GetObject(objectName);
|
||||
if (schedulerName.Equals(schedulerObject.SchedulerName))
|
||||
{
|
||||
return schedulerObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
IScheduler schedulerInRepo = SchedulerRepository.Instance.Lookup(schedulerName);
|
||||
|
||||
IScheduler schedulerInRepo = SchedulerRepository.Instance.Lookup(schedulerName)
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (schedulerInRepo == null)
|
||||
{
|
||||
throw new InvalidOperationException("No Scheduler named '" + schedulerName + "' found");
|
||||
}
|
||||
|
||||
return schedulerInRepo;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,12 @@ using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Simpl;
|
||||
using Quartz.Spi;
|
||||
using Quartz.Util;
|
||||
|
||||
using Spring.Context;
|
||||
using Spring.Context.Events;
|
||||
using Spring.Core.IO;
|
||||
@@ -81,18 +80,16 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// Default thread count to be set to thread pool.
|
||||
/// </summary>
|
||||
public const int DEFAULT_THREAD_COUNT = 10;
|
||||
public const int DefaultThreadCount = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Property name for thread count in thread pool.
|
||||
/// </summary>
|
||||
public const string PROP_THREAD_COUNT = "quartz.threadPool.threadCount";
|
||||
public const string PropThreadCount = "quartz.threadPool.threadCount";
|
||||
|
||||
[ThreadStatic]
|
||||
private static IDbProvider configTimeDbProvider;
|
||||
[ThreadStatic] private static IDbProvider configTimeDbProvider;
|
||||
|
||||
[ThreadStatic]
|
||||
private static ITaskExecutor configTimeTaskExecutor;
|
||||
[ThreadStatic] private static ITaskExecutor configTimeTaskExecutor;
|
||||
|
||||
/// <summary>
|
||||
/// Return the IDbProvider for the currently configured Quartz Scheduler,
|
||||
@@ -105,10 +102,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </remarks>
|
||||
/// <seealso cref="DbProvider" />
|
||||
/// <seealso cref="LocalDataSourceJobStore" />
|
||||
public static IDbProvider ConfigTimeDbProvider
|
||||
{
|
||||
get { return configTimeDbProvider; }
|
||||
}
|
||||
public static IDbProvider ConfigTimeDbProvider => configTimeDbProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Return the TaskExecutor for the currently configured Quartz Scheduler,
|
||||
@@ -119,10 +113,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Scheduler, and reset immediately afterwards. It is thus only available
|
||||
/// during configuration.
|
||||
/// </remarks>
|
||||
public static ITaskExecutor ConfigTimeTaskExecutor
|
||||
{
|
||||
get { return configTimeTaskExecutor; }
|
||||
}
|
||||
public static ITaskExecutor ConfigTimeTaskExecutor => configTimeTaskExecutor;
|
||||
|
||||
private IApplicationContext applicationContext;
|
||||
private string applicationContextSchedulerContextKey;
|
||||
@@ -146,7 +137,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public SchedulerFactoryObject()
|
||||
{
|
||||
schedulerFactoryType = typeof (StdSchedulerFactory);
|
||||
schedulerFactoryType = typeof(StdSchedulerFactory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -165,10 +156,11 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null || !typeof (ISchedulerFactory).IsAssignableFrom(value))
|
||||
if (value == null || !typeof(ISchedulerFactory).IsAssignableFrom(value))
|
||||
{
|
||||
throw new ArgumentException("schedulerFactoryType must implement [Quartz.ISchedulerFactory]");
|
||||
}
|
||||
|
||||
schedulerFactoryType = value;
|
||||
}
|
||||
}
|
||||
@@ -182,7 +174,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="ISchedulerFactory.GetScheduler()"/>
|
||||
public virtual string SchedulerName
|
||||
{
|
||||
set { schedulerName = value; }
|
||||
set => schedulerName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -196,7 +188,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="QuartzProperties" />
|
||||
public virtual IResource ConfigLocation
|
||||
{
|
||||
set { configLocation = value; }
|
||||
set => configLocation = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -209,7 +201,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="ConfigLocation" />
|
||||
public virtual IDictionary QuartzProperties
|
||||
{
|
||||
set { quartzProperties = value; }
|
||||
set => quartzProperties = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -225,7 +217,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="LocalTaskExecutorThreadPool"/>
|
||||
public virtual ITaskExecutor TaskExecutor
|
||||
{
|
||||
set { taskExecutor = value; }
|
||||
set => taskExecutor = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -244,7 +236,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
public virtual IDictionary SchedulerContextAsMap
|
||||
{
|
||||
set { schedulerContextMap = value; }
|
||||
set => schedulerContextMap = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -275,7 +267,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="JobDetailObject.ApplicationContextJobDataKey"/>
|
||||
public virtual string ApplicationContextSchedulerContextKey
|
||||
{
|
||||
set { applicationContextSchedulerContextKey = value; }
|
||||
set => applicationContextSchedulerContextKey = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -317,7 +309,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </remarks>
|
||||
public virtual bool ExposeSchedulerInRepository
|
||||
{
|
||||
set { exposeSchedulerInRepository = value; }
|
||||
set => exposeSchedulerInRepository = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -326,7 +318,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public virtual bool AutoStartup
|
||||
{
|
||||
set { autoStartup = value; }
|
||||
set => autoStartup = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -340,7 +332,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </remarks>
|
||||
public virtual TimeSpan StartupDelay
|
||||
{
|
||||
set { startupDelay = value; }
|
||||
set => startupDelay = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -353,7 +345,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="IScheduler.Shutdown(bool)"/>
|
||||
public virtual bool WaitForJobsToCompleteOnShutdown
|
||||
{
|
||||
set { waitForJobsToCompleteOnShutdown = value; }
|
||||
set => waitForJobsToCompleteOnShutdown = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -377,7 +369,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="LocalDataSourceJobStore" />
|
||||
public IDbProvider DbProvider
|
||||
{
|
||||
set { dbProvider = value; }
|
||||
set => dbProvider = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -422,12 +414,11 @@ namespace Spring.Scheduling.Quartz
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#region IApplicationContextAware Members
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="Spring.Context.IApplicationContext"/> that this
|
||||
/// object runs in.
|
||||
@@ -457,13 +448,9 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <exception cref="Spring.Objects.Factory.ObjectInitializationException"/>
|
||||
public virtual IApplicationContext ApplicationContext
|
||||
{
|
||||
set { applicationContext = value; }
|
||||
set => applicationContext = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Shut down the Quartz scheduler on object factory Shutdown,
|
||||
/// stopping all scheduled jobs.
|
||||
@@ -471,11 +458,9 @@ namespace Spring.Scheduling.Quartz
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Logger.Info("Shutting down Quartz Scheduler");
|
||||
scheduler.Shutdown(waitForJobsToCompleteOnShutdown);
|
||||
scheduler.Shutdown(waitForJobsToCompleteOnShutdown).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Template method that determines the Scheduler to operate on.
|
||||
/// To be implemented by subclasses.
|
||||
@@ -486,8 +471,6 @@ namespace Spring.Scheduling.Quartz
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
#region IFactoryObject Members
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance (possibly shared or independent) of the object
|
||||
/// managed by this factory.
|
||||
@@ -515,28 +498,18 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <see langword="null"/> if not known in advance.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual Type ObjectType
|
||||
{
|
||||
get { return (scheduler != null) ? scheduler.GetType() : typeof (IScheduler); }
|
||||
}
|
||||
public virtual Type ObjectType => (scheduler != null) ? scheduler.GetType() : typeof(IScheduler);
|
||||
|
||||
/// <summary>
|
||||
/// Is the object managed by this factory a singleton or a prototype?
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual bool IsSingleton
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
public virtual bool IsSingleton => true;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of IInitializingObject interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
@@ -575,6 +548,7 @@ namespace Spring.Scheduling.Quartz
|
||||
// Make given TaskExecutor available for SchedulerFactory configuration.
|
||||
configTimeTaskExecutor = taskExecutor;
|
||||
}
|
||||
|
||||
if (dbProvider != null)
|
||||
{
|
||||
// Make given db provider available for SchedulerFactory configuration.
|
||||
@@ -600,6 +574,7 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
((ISchedulerContextAware) jobFactory).SchedulerContext = scheduler.Context;
|
||||
}
|
||||
|
||||
scheduler.JobFactory = jobFactory;
|
||||
}
|
||||
}
|
||||
@@ -609,6 +584,7 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
configTimeTaskExecutor = null;
|
||||
}
|
||||
|
||||
if (dbProvider != null)
|
||||
{
|
||||
configTimeDbProvider = null;
|
||||
@@ -616,11 +592,9 @@ namespace Spring.Scheduling.Quartz
|
||||
}
|
||||
|
||||
RegisterListeners();
|
||||
RegisterJobsAndTriggers();
|
||||
RegisterJobsAndTriggers().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Load and/or apply Quartz properties to the given SchedulerFactory.
|
||||
/// </summary>
|
||||
@@ -632,11 +606,14 @@ namespace Spring.Scheduling.Quartz
|
||||
if (configLocation != null || quartzProperties != null || schedulerName != null ||
|
||||
taskExecutor != null || dbProvider != null)
|
||||
{
|
||||
throw new ArgumentException("StdSchedulerFactory required for applying Quartz properties: " + schedulerFactory);
|
||||
throw new ArgumentException("StdSchedulerFactory required for applying Quartz properties: " +
|
||||
schedulerFactory);
|
||||
}
|
||||
|
||||
// Otherwise assume that no initialization is necessary...
|
||||
return;
|
||||
}
|
||||
|
||||
NameValueCollection mergedProps = new NameValueCollection();
|
||||
|
||||
// Set necessary default properties here, as Quartz will not apply
|
||||
@@ -644,12 +621,13 @@ namespace Spring.Scheduling.Quartz
|
||||
if (taskExecutor != null)
|
||||
{
|
||||
mergedProps[StdSchedulerFactory.PropertyThreadPoolType] =
|
||||
typeof (LocalTaskExecutorThreadPool).AssemblyQualifiedName;
|
||||
typeof(LocalTaskExecutorThreadPool).AssemblyQualifiedName;
|
||||
}
|
||||
else
|
||||
{
|
||||
mergedProps.Set(StdSchedulerFactory.PropertyThreadPoolType, typeof (SimpleThreadPool).AssemblyQualifiedName);
|
||||
mergedProps[PROP_THREAD_COUNT] = Convert.ToString(DEFAULT_THREAD_COUNT);
|
||||
mergedProps.Set(StdSchedulerFactory.PropertyThreadPoolType,
|
||||
typeof(DefaultThreadPool).AssemblyQualifiedName);
|
||||
mergedProps[PropThreadCount] = Convert.ToString(DefaultThreadCount);
|
||||
}
|
||||
|
||||
if (configLocation != null)
|
||||
@@ -658,6 +636,7 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
Logger.Info("Loading Quartz config from [" + configLocation + "]");
|
||||
}
|
||||
|
||||
using (StreamReader sr = new StreamReader(configLocation.InputStream))
|
||||
{
|
||||
string line;
|
||||
@@ -680,7 +659,8 @@ namespace Spring.Scheduling.Quartz
|
||||
|
||||
if (dbProvider != null)
|
||||
{
|
||||
mergedProps[StdSchedulerFactory.PropertyJobStoreType] = typeof (LocalDataSourceJobStore).AssemblyQualifiedName;
|
||||
mergedProps[StdSchedulerFactory.PropertyJobStoreType] =
|
||||
typeof(LocalDataSourceJobStore).AssemblyQualifiedName;
|
||||
}
|
||||
|
||||
// Make sure to set the scheduler name as configured in the Spring configuration.
|
||||
@@ -724,21 +704,25 @@ namespace Spring.Scheduling.Quartz
|
||||
SchedulerRepository repository = SchedulerRepository.Instance;
|
||||
lock (repository)
|
||||
{
|
||||
IScheduler existingScheduler = (schedulerName != null ? repository.Lookup(schedulerName) : null);
|
||||
IScheduler newScheduler = schedulerFactory.GetScheduler();
|
||||
IScheduler existingScheduler = schedulerName != null
|
||||
? repository.Lookup(schedulerName).ConfigureAwait(false).GetAwaiter().GetResult()
|
||||
: null;
|
||||
|
||||
IScheduler newScheduler =
|
||||
schedulerFactory.GetScheduler().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (newScheduler == existingScheduler)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
string.Format(
|
||||
"Active Scheduler of name '{0}' already registered in Quartz SchedulerRepository. Cannot create a new Spring-managed Scheduler of the same name!",
|
||||
schedulerName));
|
||||
$"Active Scheduler of name '{schedulerName}' already registered in Quartz SchedulerRepository. Cannot create a new Spring-managed Scheduler of the same name!");
|
||||
}
|
||||
|
||||
if (!exposeSchedulerInRepository)
|
||||
{
|
||||
// Need to explicitly remove it if not intended for exposure,
|
||||
// since Quartz shares the Scheduler instance by default!
|
||||
SchedulerRepository.Instance.Remove(newScheduler.SchedulerName);
|
||||
}
|
||||
|
||||
return newScheduler;
|
||||
}
|
||||
}
|
||||
@@ -752,7 +736,8 @@ namespace Spring.Scheduling.Quartz
|
||||
// Put specified objects into Scheduler context.
|
||||
if (schedulerContextMap != null)
|
||||
{
|
||||
var dictionary = schedulerContextMap.Cast<DictionaryEntry>().ToDictionary(entry => entry.Key.ToString(), entry => entry.Value);
|
||||
var dictionary = schedulerContextMap.Cast<DictionaryEntry>()
|
||||
.ToDictionary(entry => entry.Key.ToString(), entry => entry.Value);
|
||||
scheduler.Context.PutAll(dictionary);
|
||||
}
|
||||
|
||||
@@ -764,6 +749,7 @@ namespace Spring.Scheduling.Quartz
|
||||
throw new SystemException("SchedulerFactoryObject needs to be set up in an IApplicationContext " +
|
||||
"to be able to handle an 'applicationContextSchedulerContextKey'");
|
||||
}
|
||||
|
||||
scheduler.Context.Put(applicationContextSchedulerContextKey, applicationContext);
|
||||
}
|
||||
}
|
||||
@@ -773,21 +759,23 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
/// <param name="sched">the Scheduler to start</param>
|
||||
/// <param name="startDelay">the time span to wait before starting
|
||||
/// the Scheduler asynchronously</param>
|
||||
protected virtual void StartScheduler(IScheduler sched, TimeSpan startDelay)
|
||||
/// the Scheduler asynchronously</param>
|
||||
protected virtual async Task StartScheduler(IScheduler sched, TimeSpan startDelay)
|
||||
{
|
||||
if (startDelay.TotalSeconds <= 0)
|
||||
{
|
||||
Logger.Info("Starting Quartz Scheduler now");
|
||||
sched.Start();
|
||||
await sched.Start().ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Logger.IsInfoEnabled)
|
||||
{
|
||||
Logger.InfoFormat("Will start Quartz Scheduler [{0}] in {1} seconds", sched.SchedulerName, startDelay);
|
||||
Logger.InfoFormat("Will start Quartz Scheduler [{0}] in {1} seconds", sched.SchedulerName,
|
||||
startDelay);
|
||||
}
|
||||
sched.StartDelayed(startDelay);
|
||||
|
||||
await sched.StartDelayed(startDelay).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,13 +786,13 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// Starts this instance.
|
||||
/// </summary>
|
||||
public virtual void Start()
|
||||
public virtual async Task Start()
|
||||
{
|
||||
if (scheduler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
scheduler.Start();
|
||||
await scheduler.Start().ConfigureAwait(false);
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
@@ -816,13 +804,13 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// Stops this instance.
|
||||
/// </summary>
|
||||
public virtual void Stop()
|
||||
public virtual async Task Stop()
|
||||
{
|
||||
if (scheduler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
scheduler.Standby();
|
||||
await scheduler.Standby().ConfigureAwait(false);
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
@@ -841,7 +829,7 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
try
|
||||
{
|
||||
StartScheduler(scheduler, startupDelay);
|
||||
StartScheduler(scheduler, startupDelay).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
@@ -2,26 +2,26 @@ using System;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic scheduling exception.
|
||||
/// </summary>
|
||||
public class SchedulingException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic scheduling exception.
|
||||
/// </summary>
|
||||
public class SchedulingException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchedulingException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public SchedulingException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
public SchedulingException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchedulingException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="ex">The original exception.</param>
|
||||
public SchedulingException(string message, Exception ex) : base(message, ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
public SchedulingException(string message, Exception ex) : base(message, ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,50 +13,51 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl.Triggers;
|
||||
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Convenience subclass of Quartz's <see cref="ISimpleTrigger" />
|
||||
/// class, making properties based usage easier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// SimpleTrigger itself is already a PONO but lacks sensible defaults.
|
||||
/// This class uses the Spring object name as job name, the Quartz default group
|
||||
/// ("DEFAULT") as job group, the current time as start time, and indefinite
|
||||
/// repetition, if not specified.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// This class will also register the trigger with the job name and group of
|
||||
/// a given <see cref="JobDetail" />. This allows <see cref="SchedulerFactoryObject" />
|
||||
/// to automatically register a trigger for the corresponding JobDetail,
|
||||
/// instead of registering the JobDetail separately.
|
||||
/// </p>
|
||||
/// <summary>
|
||||
/// Convenience subclass of Quartz's <see cref="ISimpleTrigger" />
|
||||
/// class, making properties based usage easier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// SimpleTrigger itself is already a PONO but lacks sensible defaults.
|
||||
/// This class uses the Spring object name as job name, the Quartz default group
|
||||
/// ("DEFAULT") as job group, the current time as start time, and indefinite
|
||||
/// repetition, if not specified.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// This class will also register the trigger with the job name and group of
|
||||
/// a given <see cref="JobDetail" />. This allows <see cref="SchedulerFactoryObject" />
|
||||
/// to automatically register a trigger for the corresponding JobDetail,
|
||||
/// instead of registering the JobDetail separately.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="ITrigger.Key" />
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="ITrigger.Key" />
|
||||
/// <seealso cref="ITrigger.StartTimeUtc" />
|
||||
/// <seealso cref="ITrigger.JobKey" />
|
||||
/// <seealso cref="SimpleTriggerObject.JobDetail" />
|
||||
/// <seealso cref="SchedulerAccessor.Triggers" />
|
||||
/// <seealso cref="SchedulerAccessor.JobDetails" />
|
||||
/// <seealso cref="CronTriggerObject" />
|
||||
public class SimpleTriggerObject : SimpleTriggerImpl, IJobDetailAwareTrigger, IObjectNameAware, IInitializingObject
|
||||
{
|
||||
private TimeSpan startDelay = TimeSpan.Zero;
|
||||
private IJobDetail jobDetail;
|
||||
private string objectName;
|
||||
private readonly Constants constants = new Constants(typeof(MisfireInstruction.SimpleTrigger), typeof(MisfireInstruction));
|
||||
/// <seealso cref="SchedulerAccessor.Triggers" />
|
||||
/// <seealso cref="SchedulerAccessor.JobDetails" />
|
||||
/// <seealso cref="CronTriggerObject" />
|
||||
public class SimpleTriggerObject : SimpleTriggerImpl, IJobDetailAwareTrigger, IObjectNameAware, IInitializingObject
|
||||
{
|
||||
private TimeSpan startDelay = TimeSpan.Zero;
|
||||
private IJobDetail jobDetail;
|
||||
private string objectName;
|
||||
|
||||
private readonly Constants constants =
|
||||
new Constants(typeof(MisfireInstruction.SimpleTrigger), typeof(MisfireInstruction));
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SimpleTriggerObject"/> class.
|
||||
@@ -66,62 +67,62 @@ namespace Spring.Scheduling.Quartz
|
||||
RepeatCount = RepeatIndefinitely;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register objects in the JobDataMap via a given Map.
|
||||
/// <p>
|
||||
/// These objects will be available to this Trigger only,
|
||||
/// in contrast to objects in the JobDetail's data map.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
public virtual IDictionary JobDataAsMap
|
||||
{
|
||||
set
|
||||
{
|
||||
foreach (DictionaryEntry entry in value)
|
||||
{
|
||||
/// <summary>
|
||||
/// Register objects in the JobDataMap via a given Map.
|
||||
/// <p>
|
||||
/// These objects will be available to this Trigger only,
|
||||
/// in contrast to objects in the JobDetail's data map.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
public virtual IDictionary JobDataAsMap
|
||||
{
|
||||
set
|
||||
{
|
||||
foreach (DictionaryEntry entry in value)
|
||||
{
|
||||
JobDataMap.Put((string) entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the misfire instruction via the name of the corresponding
|
||||
/// constant in the SimpleTrigger class.
|
||||
/// <summary>
|
||||
/// Set the misfire instruction via the name of the corresponding
|
||||
/// constant in the SimpleTrigger class.
|
||||
/// Default is <see cref="MisfireInstruction.SmartPolicy" />.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
/// <seealso cref="MisfireInstruction.SimpleTrigger.FireNow" />
|
||||
/// <seealso cref="MisfireInstruction.SimpleTrigger.RescheduleNextWithExistingCount" />
|
||||
/// <seealso cref="MisfireInstruction.SimpleTrigger.RescheduleNextWithRemainingCount" />
|
||||
/// <seealso cref="MisfireInstruction.SimpleTrigger.RescheduleNowWithExistingRepeatCount" />
|
||||
/// <seealso cref="MisfireInstruction.SimpleTrigger.RescheduleNowWithRemainingRepeatCount" />
|
||||
/// <seealso cref="MisfireInstruction.SmartPolicy" />
|
||||
public virtual string MisfireInstructionName
|
||||
{
|
||||
set { MisfireInstruction = constants.AsNumber(value); }
|
||||
}
|
||||
public virtual string MisfireInstructionName
|
||||
{
|
||||
set => MisfireInstruction = constants.AsNumber(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the delay before starting the job for the first time.
|
||||
/// The given time span will be added to the current
|
||||
/// time to calculate the start time. Default is <see cref="TimeSpan.Zero" />.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This delay will just be applied if no custom start time was
|
||||
/// specified. However, in typical usage within a Spring context,
|
||||
/// the start time will be the container startup time anyway.
|
||||
/// Specifying a relative delay is appropriate in that case.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ITrigger.StartTimeUtc" />
|
||||
public virtual TimeSpan StartDelay
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the delay before starting the job for the first time.
|
||||
/// The given time span will be added to the current
|
||||
/// time to calculate the start time. Default is <see cref="TimeSpan.Zero" />.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This delay will just be applied if no custom start time was
|
||||
/// specified. However, in typical usage within a Spring context,
|
||||
/// the start time will be the container startup time anyway.
|
||||
/// Specifying a relative delay is appropriate in that case.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ITrigger.StartTimeUtc" />
|
||||
public virtual TimeSpan StartDelay
|
||||
{
|
||||
set
|
||||
{
|
||||
AssertUtils.State(value >= TimeSpan.Zero, "Start delay cannot be negative.");
|
||||
startDelay = value;
|
||||
}
|
||||
get { return startDelay; }
|
||||
}
|
||||
get => startDelay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
@@ -135,25 +136,24 @@ namespace Spring.Scheduling.Quartz
|
||||
/// method or a custom init-method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set { objectName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the JobDetail that this trigger should be associated with.
|
||||
/// <p>
|
||||
/// This is typically used with a object reference if the JobDetail
|
||||
/// is a Spring-managed object. Alternatively, the trigger can also
|
||||
/// be associated with a job by name and group.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
public virtual IJobDetail JobDetail
|
||||
{
|
||||
get { return jobDetail; }
|
||||
set { jobDetail = value; }
|
||||
}
|
||||
public virtual string ObjectName
|
||||
{
|
||||
set => objectName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the JobDetail that this trigger should be associated with.
|
||||
/// <p>
|
||||
/// This is typically used with a object reference if the JobDetail
|
||||
/// is a Spring-managed object. Alternatively, the trigger can also
|
||||
/// be associated with a job by name and group.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
public virtual IJobDetail JobDetail
|
||||
{
|
||||
get => jobDetail;
|
||||
set => jobDetail = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
@@ -181,30 +181,33 @@ namespace Spring.Scheduling.Quartz
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
if (StartTimeUtc == DateTimeOffset.MinValue)
|
||||
{
|
||||
StartTimeUtc = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
if (StartDelay > TimeSpan.Zero)
|
||||
{
|
||||
StartTimeUtc = DateTime.UtcNow.Add(startDelay);
|
||||
}
|
||||
|
||||
if (Name == null)
|
||||
{
|
||||
Name = objectName;
|
||||
}
|
||||
if (Group == null)
|
||||
{
|
||||
if (Name == null)
|
||||
{
|
||||
Name = objectName;
|
||||
}
|
||||
|
||||
if (Group == null)
|
||||
{
|
||||
Group = SchedulerConstants.DefaultGroup;
|
||||
}
|
||||
if (jobDetail != null)
|
||||
{
|
||||
JobName = jobDetail.Key.Name;
|
||||
JobGroup = jobDetail.Key.Group;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jobDetail != null)
|
||||
{
|
||||
JobName = jobDetail.Key.Name;
|
||||
JobGroup = jobDetail.Key.Group;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Reflection;
|
||||
|
||||
using Quartz.Impl.AdoJobStore.Common;
|
||||
|
||||
using IDbMetadata=Spring.Data.Common.IDbMetadata;
|
||||
using IDbMetadata = Spring.Data.Common.IDbMetadata;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
@@ -48,16 +47,15 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the command.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDbCommand CreateCommand()
|
||||
public DbCommand CreateCommand()
|
||||
{
|
||||
return dbProvider.CreateCommand();
|
||||
return (DbCommand) dbProvider.CreateCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -73,9 +71,9 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Creates the connection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDbConnection CreateConnection()
|
||||
public DbConnection CreateConnection()
|
||||
{
|
||||
return dbProvider.CreateConnection();
|
||||
return (DbConnection) dbProvider.CreateConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,18 +99,15 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The connection string.</value>
|
||||
public string ConnectionString
|
||||
{
|
||||
get { return dbProvider.ConnectionString; }
|
||||
set { dbProvider.ConnectionString = value; }
|
||||
get => dbProvider.ConnectionString;
|
||||
set => dbProvider.ConnectionString = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the metadata.
|
||||
/// </summary>
|
||||
/// <value>The metadata.</value>
|
||||
public DbMetadata Metadata
|
||||
{
|
||||
get { return metadata; }
|
||||
}
|
||||
public DbMetadata Metadata => metadata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -149,7 +144,6 @@ namespace Spring.Scheduling.Quartz
|
||||
// use standard binary type
|
||||
dbTypeBinary = DbType.Binary;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -158,8 +152,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The name of the product.</value>
|
||||
public override string ProductName
|
||||
{
|
||||
get { return metadata.ProductName; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ProductName;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -168,8 +162,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The type of the connection.</value>
|
||||
public override Type ConnectionType
|
||||
{
|
||||
get { return metadata.ConnectionType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ConnectionType;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -178,8 +172,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The type of the command.</value>
|
||||
public override Type CommandType
|
||||
{
|
||||
get { return metadata.CommandType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.CommandType;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -188,28 +182,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The type of the parameter.</value>
|
||||
public override Type ParameterType
|
||||
{
|
||||
get { return metadata.ParameterType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the command builder.
|
||||
/// </summary>
|
||||
/// <value>The type of the command builder.</value>
|
||||
public override Type CommandBuilderType
|
||||
{
|
||||
get { return metadata.CommandBuilderType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the command builder derive parameters method.
|
||||
/// </summary>
|
||||
/// <value>The command builder derive parameters method.</value>
|
||||
public override MethodInfo CommandBuilderDeriveParametersMethod
|
||||
{
|
||||
get { return metadata.CommandBuilderDeriveParametersMethod; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ParameterType;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -218,8 +192,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The parameter name prefix.</value>
|
||||
public override string ParameterNamePrefix
|
||||
{
|
||||
get { return metadata.ParameterNamePrefix; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ParameterNamePrefix;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -228,8 +202,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The type of the exception.</value>
|
||||
public override Type ExceptionType
|
||||
{
|
||||
get { return metadata.ExceptionType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ExceptionType;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -238,8 +212,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value><c>true</c> if [bind by name]; otherwise, <c>false</c>.</value>
|
||||
public override bool BindByName
|
||||
{
|
||||
get { return metadata.BindByName; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.BindByName;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -248,8 +222,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The type of the parameter db.</value>
|
||||
public override Type ParameterDbType
|
||||
{
|
||||
get { return metadata.ParameterDbType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ParameterDbType;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -258,8 +232,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The parameter db type property.</value>
|
||||
public override PropertyInfo ParameterDbTypeProperty
|
||||
{
|
||||
get { return metadata.ParameterDbTypeProperty; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ParameterDbTypeProperty;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -268,18 +242,15 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <value>The parameter is nullable property.</value>
|
||||
public override PropertyInfo ParameterIsNullableProperty
|
||||
{
|
||||
get { return metadata.ParameterIsNullableProperty; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.ParameterIsNullableProperty;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the db binary.
|
||||
/// </summary>
|
||||
/// <value>The type of the db binary.</value>
|
||||
public override Enum DbBinaryType
|
||||
{
|
||||
get { return dbTypeBinary; }
|
||||
}
|
||||
public override Enum DbBinaryType => dbTypeBinary;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [use parameter name prefix in parameter collection].
|
||||
@@ -289,9 +260,8 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </value>
|
||||
public override bool UseParameterNamePrefixInParameterCollection
|
||||
{
|
||||
get { return metadata.UseParameterNamePrefixInParameterCollection; }
|
||||
set { throw new NotSupportedException(); }
|
||||
get => metadata.UseParameterNamePrefixInParameterCollection;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
using Spring.Objects;
|
||||
@@ -50,7 +51,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </remarks>
|
||||
public virtual string[] IgnoredUnknownProperties
|
||||
{
|
||||
set { ignoredUnknownProperties = value; }
|
||||
set => ignoredUnknownProperties = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,10 +61,9 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <seealso cref="IScheduler.Context"/>
|
||||
public virtual SchedulerContext SchedulerContext
|
||||
{
|
||||
set { schedulerContext = value; }
|
||||
set => schedulerContext = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create the job instance, populating it with property values taken
|
||||
/// from the scheduler context, job data map and trigger data map.
|
||||
@@ -78,6 +78,7 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
pvs.AddAll(schedulerContext);
|
||||
}
|
||||
|
||||
pvs.AddAll(bundle.JobDetail.JobDataMap);
|
||||
pvs.AddAll(bundle.Trigger.JobDataMap);
|
||||
if (ignoredUnknownProperties != null)
|
||||
@@ -90,6 +91,7 @@ namespace Spring.Scheduling.Quartz
|
||||
pvs.Remove(propName);
|
||||
}
|
||||
}
|
||||
|
||||
ow.SetPropertyValues(pvs);
|
||||
}
|
||||
else
|
||||
@@ -97,6 +99,7 @@ namespace Spring.Scheduling.Quartz
|
||||
ow.SetPropertyValues(pvs, true);
|
||||
}
|
||||
}
|
||||
|
||||
return ow.WrappedInstance;
|
||||
}
|
||||
|
||||
@@ -30,4 +30,4 @@ namespace Spring.Scheduling.Quartz
|
||||
// No implementation, just an addition of the tag interface StatefulJob
|
||||
// in order to allow stateful method invoking jobs.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Spring.Scheduling
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TaskRejectedException.
|
||||
/// </summary>
|
||||
public class TaskRejectedException : ApplicationException
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net452</TargetFramework>
|
||||
<Description>Spring.NET Integration with the Quartz Scheduling Library 2.x</Description>
|
||||
<TargetFrameworks>netstandard2.0;$(TargetFullFrameworkVersion)</TargetFrameworks>
|
||||
<Description>Spring.NET Integration with the Quartz Scheduling Library 3.x</Description>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Core\Spring.Core.csproj" />
|
||||
<ProjectReference Include="..\Spring.Data\Spring.Data.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Quartz" Version="2.6.2" />
|
||||
<PackageReference Include="Quartz" Version="3.0.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\GenCommonAssemblyInfo.cs">
|
||||
@@ -63,7 +63,7 @@ namespace Spring.Data.Core
|
||||
|
||||
TransactionOptions txOptions = new TransactionOptions();
|
||||
txOptions.IsolationLevel = IsolationLevel.ReadCommitted;
|
||||
txAdapter.CreateTransactionScope(TransactionScopeOption.Required, txOptions, EnterpriseServicesInteropOption.None);
|
||||
txAdapter.CreateTransactionScope(TransactionScopeOption.Required, txOptions, TransactionScopeAsyncFlowOption.Enabled);
|
||||
txAdapter.Complete();
|
||||
txAdapter.Dispose();
|
||||
}
|
||||
@@ -103,7 +103,7 @@ namespace Spring.Data.Core
|
||||
}
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
A.CallTo(() => txAdapter.CreateTransactionScope(TransactionScopeOption.Required, txOptions, EnterpriseServicesInteropOption.None)).MustHaveHappenedOnceExactly();
|
||||
A.CallTo(() => txAdapter.CreateTransactionScope(TransactionScopeOption.Required, txOptions, TransactionScopeAsyncFlowOption.Enabled)).MustHaveHappenedOnceExactly();
|
||||
A.CallTo(() => txAdapter.Dispose()).MustHaveHappenedOnceExactly();
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace Spring.Data.Core
|
||||
return null;
|
||||
});
|
||||
|
||||
A.CallTo(() => txAdapter.CreateTransactionScope(TransactionScopeOption.RequiresNew, txOptions, EnterpriseServicesInteropOption.None)).MustHaveHappenedTwiceExactly();
|
||||
A.CallTo(() => txAdapter.CreateTransactionScope(TransactionScopeOption.RequiresNew, txOptions, TransactionScopeAsyncFlowOption.Enabled)).MustHaveHappenedTwiceExactly();
|
||||
A.CallTo(() => txAdapter.Dispose()).MustHaveHappenedTwiceExactly();
|
||||
A.CallTo(() => txAdapter.Complete()).MustHaveHappenedOnceExactly();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2011 the original author or authors.
|
||||
*
|
||||
@@ -16,47 +14,31 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Transactions;
|
||||
using Common.Logging;
|
||||
using Spring.Objects;
|
||||
using Spring.Transaction;
|
||||
using Spring.Transaction.Interceptor;
|
||||
using Spring.Transaction.Support;
|
||||
using IsolationLevel=System.Data.IsolationLevel;
|
||||
|
||||
#endregion
|
||||
using IsolationLevel = System.Data.IsolationLevel;
|
||||
|
||||
namespace Spring.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Group together multiple ITestObjectDao operations.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class TestObjectMgr : ITestObjectMgr
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Group together multiple ITestObjectDao operations.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class TestObjectMgr : ITestObjectMgr
|
||||
{
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(TestObjectMgr));
|
||||
#endregion
|
||||
|
||||
#region Constructor (s)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TestObjectMgr"/> class.
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TestObjectMgr"/> class.
|
||||
/// </summary>
|
||||
public TestObjectMgr()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Methods
|
||||
public TestObjectMgr()
|
||||
{
|
||||
}
|
||||
|
||||
[Transaction()]
|
||||
public void SaveTwoTestObjects(TestObject to1, TestObject to2)
|
||||
@@ -65,14 +47,12 @@ namespace Spring.Data
|
||||
}
|
||||
|
||||
[Transaction(TransactionPropagation.Required, IsolationLevel.Unspecified, Timeout = 50,
|
||||
RollbackFor = new Type[]{typeof(ArgumentNullException)},
|
||||
ReadOnly = false,
|
||||
EnterpriseServicesInteropOption = System.Transactions.EnterpriseServicesInteropOption.Automatic,
|
||||
NoRollbackFor = new Type[] { typeof(ArithmeticException), typeof(NotSupportedException) })]
|
||||
public void DeleteTwoTestObjects(string name1, string name2)
|
||||
RollbackFor = new Type[] {typeof(ArgumentNullException)},
|
||||
ReadOnly = false,
|
||||
AsyncFlowOption = TransactionScopeAsyncFlowOption.Enabled,
|
||||
NoRollbackFor = new Type[] {typeof(ArithmeticException), typeof(NotSupportedException)})]
|
||||
public void DeleteTwoTestObjects(string name1, string name2)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,49 +5,17 @@ namespace Spring.Transaction
|
||||
{
|
||||
public class MockTxnDefinition : ITransactionDefinition
|
||||
{
|
||||
private int _transactionTimeout = DefaultTransactionDefinition.TIMEOUT_DEFAULT;
|
||||
private TransactionPropagation _transactionPropagation = TransactionPropagation.NotSupported;
|
||||
private bool _readOnly = false;
|
||||
private string _name = null;
|
||||
private System.Transactions.EnterpriseServicesInteropOption _esInteropOption;
|
||||
public bool ReadOnly { get; set; }
|
||||
|
||||
#region ITransactionDefinition Members
|
||||
public int TransactionTimeout { get; set; } = DefaultTransactionDefinition.TIMEOUT_DEFAULT;
|
||||
|
||||
public bool ReadOnly
|
||||
{
|
||||
get { return _readOnly; }
|
||||
set { _readOnly = value; }
|
||||
}
|
||||
public IsolationLevel TransactionIsolationLevel => IsolationLevel.Unspecified;
|
||||
|
||||
public int TransactionTimeout
|
||||
{
|
||||
get { return _transactionTimeout; }
|
||||
set { _transactionTimeout = value; }
|
||||
}
|
||||
public TransactionPropagation PropagationBehavior { get; set; } = TransactionPropagation.NotSupported;
|
||||
|
||||
public IsolationLevel TransactionIsolationLevel
|
||||
{
|
||||
get { return IsolationLevel.Unspecified; }
|
||||
}
|
||||
public string Name { get; } = null;
|
||||
|
||||
public TransactionPropagation PropagationBehavior
|
||||
{
|
||||
get { return _transactionPropagation; }
|
||||
set { _transactionPropagation = value; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public System.Transactions.EnterpriseServicesInteropOption EnterpriseServicesInteropOption
|
||||
{
|
||||
get { return _esInteropOption; }
|
||||
set { _esInteropOption = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
public System.Transactions.TransactionScopeAsyncFlowOption AsyncFlowOption { get; set; }
|
||||
}
|
||||
|
||||
public class MockTxnPlatformMgrAbstract : AbstractPlatformTransactionManager
|
||||
@@ -68,32 +36,18 @@ namespace Spring.Transaction
|
||||
_isExistingTransaction = true;
|
||||
}
|
||||
|
||||
public object Transaction
|
||||
{
|
||||
get { return _transaction; }
|
||||
}
|
||||
public object Transaction => _transaction;
|
||||
|
||||
public bool Savepoints
|
||||
{
|
||||
set { _useSavepointForNestedTransaction = value; }
|
||||
set => _useSavepointForNestedTransaction = value;
|
||||
}
|
||||
|
||||
public int DoBeginCallCount
|
||||
{
|
||||
get { return _doBeginCalls; }
|
||||
}
|
||||
public int DoBeginCallCount => _doBeginCalls;
|
||||
|
||||
public int DoGetTransactionCallCount
|
||||
{
|
||||
get { return _doGetTxnCalls; }
|
||||
}
|
||||
public int DoGetTransactionCallCount => _doGetTxnCalls;
|
||||
|
||||
public int IsExistingTransactionCallCount
|
||||
{
|
||||
get { return _isExistingTxnCalls; }
|
||||
}
|
||||
|
||||
#region AbstractPlatformTransactionManager Impls
|
||||
public int IsExistingTransactionCallCount => _isExistingTxnCalls;
|
||||
|
||||
protected override void DoResume(object transaction, object suspendedResources)
|
||||
{
|
||||
@@ -144,7 +98,5 @@ namespace Spring.Transaction
|
||||
{
|
||||
return _useSavepointForNestedTransaction;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net"
|
||||
xmlns:aop="http://www.springframework.net/aop"
|
||||
xmlns:db="http://www.springframework.net/database"
|
||||
xmlns:tx="http://www.springframework.net/tx">
|
||||
|
||||
|
||||
<!-- Property placeholder configurer for database settings -->
|
||||
|
||||
<object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
||||
<property name="ConfigSections" value="appSettings"/>
|
||||
</object>
|
||||
|
||||
<!-- DB -->
|
||||
|
||||
<db:provider id="dbProvider" provider="SqlServer-2.0" connectionString="${ConnectionString}"/>
|
||||
|
||||
<object id="transactionManager" type="Spring.Data.Core.TxScopeTransactionManager, Spring.Data">
|
||||
|
||||
</object>
|
||||
|
||||
<!-- And actual Quartz -->
|
||||
|
||||
<object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<property name="AutoStartup" value="true" />
|
||||
<property name="StartupDelay" value="5s" />
|
||||
<property name="QuartzProperties">
|
||||
<dictionary>
|
||||
<entry key="quartz.threadPool.threadCount" value="10"/>
|
||||
<entry key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
|
||||
<entry key="quartz.threadPool.threadPriority" value="Normal"/>
|
||||
<entry key="quartz.jobStore.misfireThreshold" value="60000"/>
|
||||
<entry key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz"/>
|
||||
<entry key="quartz.jobStore.useProperties" value="false"/>
|
||||
<entry key="quartz.jobStore.tablePrefix" value="QRTZ_"/>
|
||||
<entry key="quartz.jobStore.lockHandler.type" value="Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz"/>
|
||||
|
||||
</dictionary>
|
||||
</property>
|
||||
<property name="triggers">
|
||||
<list>
|
||||
<ref object="simpleTrigger" />
|
||||
</list>
|
||||
</property>
|
||||
<property name="DbProvider" ref="dbProvider" />
|
||||
<property name="TransactionManager" ref="transactionManager" />
|
||||
</object>
|
||||
|
||||
<object id="testJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz2">
|
||||
<property name="JobType" value="Spring.Scheduling.Quartz.Integration.Tests.TestJob, Spring.Scheduling.Quartz2.Integration.Tests" />
|
||||
</object>
|
||||
|
||||
<object id="simpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<!-- see the example of method invoking job above -->
|
||||
<property name="jobDetail" ref="testJob" />
|
||||
<!-- 2 seconds -->
|
||||
<property name="startDelay" value="2s" />
|
||||
<!-- repeat every 3 seconds -->
|
||||
<property name="repeatInterval" value="3s" />
|
||||
</object>
|
||||
|
||||
|
||||
</objects>
|
||||
@@ -1,7 +1,7 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright © 2002-2007 the original author or authors.
|
||||
* Copyright <EFBFBD> 2002-2007 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.
|
||||
@@ -21,32 +21,32 @@
|
||||
#region Imports
|
||||
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Spring.Context;
|
||||
using Spring.Context.Support;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Scheduling.Quartz.Integration.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class LocalDataSourceJobStoreTest
|
||||
public class LocalDataSourceJobStoreTest
|
||||
{
|
||||
private IApplicationContext ctx;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
ctx = new XmlApplicationContext("assembly://Spring.Scheduling.Quartz2.Integration.Tests/Spring.Scheduling.Quartz/LocalDataSourceJobStoreTest.xml");
|
||||
ctx = new XmlApplicationContext(
|
||||
"assembly://Spring.Scheduling.Quartz3.Integration.Tests/Spring.Scheduling.Quartz/LocalDataSourceJobStoreTest.xml");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Appveyor problems")]
|
||||
[Explicit("Appveyor problems")]
|
||||
public void TestLocalDataSourceJobStore()
|
||||
{
|
||||
// sleep 20 seconds
|
||||
Thread.Sleep(20000);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<objects xmlns="http://www.springframework.net"
|
||||
xmlns:aop="http://www.springframework.net/aop"
|
||||
xmlns:db="http://www.springframework.net/database"
|
||||
xmlns:tx="http://www.springframework.net/tx">
|
||||
|
||||
|
||||
<!-- Property placeholder configurer for database settings -->
|
||||
|
||||
<object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
||||
<property name="ConfigSections" value="appSettings" />
|
||||
</object>
|
||||
|
||||
<!-- DB -->
|
||||
|
||||
<db:provider id="dbProvider" provider="SqlServer-2.0" connectionString="${ConnectionString}" />
|
||||
|
||||
<object id="transactionManager" type="Spring.Data.Core.TxScopeTransactionManager, Spring.Data">
|
||||
|
||||
</object>
|
||||
|
||||
<!-- And actual Quartz -->
|
||||
|
||||
<object id="quartzSchedulerFactory" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="AutoStartup" value="true" />
|
||||
<property name="StartupDelay" value="5s" />
|
||||
<property name="QuartzProperties">
|
||||
<dictionary>
|
||||
<entry key="quartz.serializer.type" value="binary" />
|
||||
<entry key="quartz.threadPool.threadCount" value="10" />
|
||||
<entry key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
|
||||
<entry key="quartz.threadPool.threadPriority" value="Normal" />
|
||||
<entry key="quartz.jobStore.misfireThreshold" value="60000" />
|
||||
<entry key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz" />
|
||||
<entry key="quartz.jobStore.useProperties" value="false" />
|
||||
<entry key="quartz.jobStore.tablePrefix" value="QRTZ_" />
|
||||
<entry key="quartz.jobStore.lockHandler.type" value="Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz" />
|
||||
</dictionary>
|
||||
</property>
|
||||
<property name="triggers">
|
||||
<list>
|
||||
<ref object="simpleTrigger" />
|
||||
</list>
|
||||
</property>
|
||||
<property name="DbProvider" ref="dbProvider" />
|
||||
<property name="TransactionManager" ref="transactionManager" />
|
||||
</object>
|
||||
|
||||
<object id="testJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz3">
|
||||
<property name="JobType"
|
||||
value="Spring.Scheduling.Quartz.Integration.Tests.TestJob, Spring.Scheduling.Quartz3.Integration.Tests" />
|
||||
</object>
|
||||
|
||||
<object id="simpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<!-- see the example of method invoking job above -->
|
||||
<property name="jobDetail" ref="testJob" />
|
||||
<!-- 2 seconds -->
|
||||
<property name="startDelay" value="2s" />
|
||||
<!-- repeat every 3 seconds -->
|
||||
<property name="repeatInterval" value="3s" />
|
||||
</object>
|
||||
|
||||
|
||||
</objects>
|
||||
@@ -1,14 +1,15 @@
|
||||
using System;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Quartz;
|
||||
|
||||
namespace Spring.Scheduling.Quartz.Integration.Tests
|
||||
{
|
||||
public class TestJob : IJob
|
||||
{
|
||||
public void Execute(IJobExecutionContext context)
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
Console.WriteLine("Executing Execute!");
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public void DoIt()
|
||||
@@ -1,11 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net452</TargetFramework>
|
||||
<TargetFrameworks>netcoreapp2.1;$(TargetFullFrameworkVersion)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Data\Spring.Data.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Scheduling.Quartz2\Spring.Scheduling.Quartz2.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Scheduling.Quartz3\Spring.Scheduling.Quartz3.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FakeItEasy" Version="$(FakeItEasyVersion)" />
|
||||
@@ -19,7 +19,6 @@ using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
@@ -22,8 +22,6 @@ using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Job;
|
||||
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
@@ -20,7 +20,6 @@ using System.Collections;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
|
||||
using Spring.Context.Support;
|
||||
|
||||
@@ -24,7 +24,6 @@ using NUnit.Framework;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Impl.Triggers;
|
||||
using Quartz.Job;
|
||||
using Quartz.Spi;
|
||||
|
||||
using Spring.Objects.Support;
|
||||
@@ -151,7 +150,15 @@ namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
IJobDetail jd = new JobDetailImpl("jobName", "jobGroup", typeof(NoOpJob));
|
||||
IOperableTrigger trigger = new SimpleTriggerImpl("triggerName", "triggerGroup");
|
||||
TriggerFiredBundle retValue = new TriggerFiredBundle(jd, trigger, null, false, null, null, null, null);
|
||||
TriggerFiredBundle retValue = new TriggerFiredBundle(
|
||||
jd,
|
||||
trigger,
|
||||
null,
|
||||
false,
|
||||
DateTimeOffset.UtcNow,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
return retValue;
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using FakeItEasy;
|
||||
|
||||
using NUnit.Framework;
|
||||
@@ -46,18 +46,18 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Executes parametrized test.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObject()
|
||||
public async Task TestSchedulerFactoryObject()
|
||||
{
|
||||
DoTestSchedulerFactoryObject(false, false);
|
||||
await DoTestSchedulerFactoryObject(false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes parametrized test.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObjectWithExplicitJobDetail()
|
||||
public async Task TestSchedulerFactoryObjectWithExplicitJobDetail()
|
||||
{
|
||||
DoTestSchedulerFactoryObject(true, false);
|
||||
await DoTestSchedulerFactoryObject(true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,12 +65,12 @@ namespace Spring.Scheduling.Quartz
|
||||
/// </summary>
|
||||
[Test]
|
||||
[Ignore("Requires change to MethodInvoker for overriding target object and type")]
|
||||
public void TestSchedulerFactoryObjectWithPrototypeJob()
|
||||
public async Task TestSchedulerFactoryObjectWithPrototypeJob()
|
||||
{
|
||||
DoTestSchedulerFactoryObject(false, true);
|
||||
await DoTestSchedulerFactoryObject(false, true);
|
||||
}
|
||||
|
||||
private void DoTestSchedulerFactoryObject(bool explicitJobDetail, bool prototypeJob)
|
||||
private async Task DoTestSchedulerFactoryObject(bool explicitJobDetail, bool prototypeJob)
|
||||
{
|
||||
TestObject tb = new TestObject("tb", 99);
|
||||
JobDetailObject jobDetail0 = new JobDetailObject();
|
||||
@@ -116,8 +116,8 @@ namespace Spring.Scheduling.Quartz
|
||||
IScheduler scheduler = A.Fake<IScheduler>();
|
||||
|
||||
A.CallTo(() => scheduler.Context).Returns(new SchedulerContext());
|
||||
A.CallTo(() => scheduler.GetTrigger(A<TriggerKey>._)).Returns(null);
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._)).Returns(null);
|
||||
A.CallTo(() => scheduler.GetTrigger(A<TriggerKey>._, A<CancellationToken>._)).Returns(Task.FromResult<ITrigger>(null));
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._, A<CancellationToken>._)).Returns(Task.FromResult<IJobDetail>(null));
|
||||
|
||||
SchedulerFactoryObject schedulerFactoryObject = new TestSchedulerFactoryObject(scheduler);
|
||||
schedulerFactoryObject.JobFactory = null;
|
||||
@@ -132,42 +132,42 @@ namespace Spring.Scheduling.Quartz
|
||||
try
|
||||
{
|
||||
schedulerFactoryObject.AfterPropertiesSet();
|
||||
schedulerFactoryObject.Start();
|
||||
await schedulerFactoryObject.Start();
|
||||
}
|
||||
finally
|
||||
{
|
||||
schedulerFactoryObject.Dispose();
|
||||
}
|
||||
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger0)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger1)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger0, A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger1, A<CancellationToken>._)).MustHaveHappened();
|
||||
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true, A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true, A<CancellationToken>._)).MustHaveHappened();
|
||||
|
||||
A.CallTo(() => scheduler.Start()).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.Shutdown(false)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.Start(A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.Shutdown(false, A<CancellationToken>._)).MustHaveHappened();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes parametrized test.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObjectWithExistingJobs()
|
||||
public async Task TestSchedulerFactoryObjectWithExistingJobs()
|
||||
{
|
||||
DoTestSchedulerFactoryObjectWithExistingJobs(false);
|
||||
await DoTestSchedulerFactoryObjectWithExistingJobs(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes parametrized test.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObjectWithOverwriteExistingJobs()
|
||||
public async Task TestSchedulerFactoryObjectWithOverwriteExistingJobs()
|
||||
{
|
||||
DoTestSchedulerFactoryObjectWithExistingJobs(true);
|
||||
await DoTestSchedulerFactoryObjectWithExistingJobs(true);
|
||||
}
|
||||
|
||||
private void DoTestSchedulerFactoryObjectWithExistingJobs(bool overwrite)
|
||||
private async Task DoTestSchedulerFactoryObjectWithExistingJobs(bool overwrite)
|
||||
{
|
||||
TestObject tb = new TestObject("tb", 99);
|
||||
JobDetailObject jobDetail0 = new JobDetailObject();
|
||||
@@ -202,13 +202,13 @@ namespace Spring.Scheduling.Quartz
|
||||
|
||||
IScheduler scheduler = A.Fake<IScheduler>();
|
||||
A.CallTo(() => scheduler.Context).Returns(new SchedulerContext());
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._)).Returns(null);
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup))).Returns(null);
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup))).Returns(new SimpleTriggerImpl());
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._, A<CancellationToken>._)).Returns(Task.FromResult<IJobDetail>(null));
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).Returns(Task.FromResult<ITrigger>(null));
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).Returns(Task.FromResult<ITrigger>(new SimpleTriggerImpl()));
|
||||
|
||||
if (overwrite)
|
||||
{
|
||||
A.CallTo(() => scheduler.RescheduleJob(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup), trigger1)).Returns(DateTime.UtcNow);
|
||||
A.CallTo(() => scheduler.RescheduleJob(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup), trigger1, A<CancellationToken>._)).Returns(DateTime.UtcNow);
|
||||
}
|
||||
|
||||
SchedulerFactoryObject schedulerFactoryObject = new TestSchedulerFactoryObject(scheduler);
|
||||
@@ -224,38 +224,38 @@ namespace Spring.Scheduling.Quartz
|
||||
try
|
||||
{
|
||||
schedulerFactoryObject.AfterPropertiesSet();
|
||||
schedulerFactoryObject.Start();
|
||||
await schedulerFactoryObject.Start();
|
||||
}
|
||||
finally
|
||||
{
|
||||
schedulerFactoryObject.Dispose();
|
||||
}
|
||||
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger0)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.Start()).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.Shutdown(false)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true, A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger0, A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.Start(A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.Shutdown(false, A<CancellationToken>._)).MustHaveHappened();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes parametrized test.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObjectWithExistingJobsAndRaceCondition()
|
||||
public async Task TestSchedulerFactoryObjectWithExistingJobsAndRaceCondition()
|
||||
{
|
||||
DoTestSchedulerFactoryObjectWithExistingJobsAndRaceCondition(false);
|
||||
await DoTestSchedulerFactoryObjectWithExistingJobsAndRaceCondition(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes parametrized test.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObjectWithOverwriteExistingJobsAndRaceCondition()
|
||||
public async Task TestSchedulerFactoryObjectWithOverwriteExistingJobsAndRaceCondition()
|
||||
{
|
||||
DoTestSchedulerFactoryObjectWithExistingJobsAndRaceCondition(true);
|
||||
await DoTestSchedulerFactoryObjectWithExistingJobsAndRaceCondition(true);
|
||||
}
|
||||
|
||||
private void DoTestSchedulerFactoryObjectWithExistingJobsAndRaceCondition(bool overwrite)
|
||||
private async Task DoTestSchedulerFactoryObjectWithExistingJobsAndRaceCondition(bool overwrite)
|
||||
{
|
||||
TestObject tb = new TestObject("tb", 99);
|
||||
JobDetailObject jobDetail0 = new JobDetailObject();
|
||||
@@ -290,24 +290,24 @@ namespace Spring.Scheduling.Quartz
|
||||
|
||||
IScheduler scheduler = A.Fake<IScheduler>();
|
||||
A.CallTo(() => scheduler.Context).Returns(new SchedulerContext());
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._)).Returns(null);
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup))).Returns(null);
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup))).Returns(new SimpleTriggerImpl());
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._, A<CancellationToken>._)).Returns(Task.FromResult<IJobDetail>(null));
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).Returns(Task.FromResult<ITrigger>(null));
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).Returns(Task.FromResult<ITrigger>(new SimpleTriggerImpl()));
|
||||
if (overwrite)
|
||||
{
|
||||
scheduler.AddJob(jobDetail1, true);
|
||||
A.CallTo(() => scheduler.RescheduleJob(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup), trigger1)).Returns(DateTime.UtcNow);
|
||||
await scheduler.AddJob(jobDetail1, true);
|
||||
A.CallTo(() => scheduler.RescheduleJob(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup), trigger1, A<CancellationToken>._)).Returns(DateTime.UtcNow);
|
||||
}
|
||||
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger0)).Throws(new ObjectAlreadyExistsException(""));
|
||||
A.CallTo(() => scheduler.ScheduleJob(trigger0, A<CancellationToken>._)).Throws(new ObjectAlreadyExistsException(""));
|
||||
|
||||
if (overwrite)
|
||||
{
|
||||
A.CallTo(() => scheduler.RescheduleJob(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup), trigger0)).Returns(DateTime.UtcNow);
|
||||
A.CallTo(() => scheduler.RescheduleJob(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup), trigger0, A<CancellationToken>._)).Returns(DateTime.UtcNow);
|
||||
}
|
||||
|
||||
scheduler.Start();
|
||||
scheduler.Shutdown(false);
|
||||
await scheduler.Start();
|
||||
await scheduler.Shutdown(false);
|
||||
|
||||
SchedulerFactoryObject schedulerFactoryObject = new TestSchedulerFactoryObject(scheduler);
|
||||
|
||||
@@ -323,14 +323,14 @@ namespace Spring.Scheduling.Quartz
|
||||
try
|
||||
{
|
||||
schedulerFactoryObject.AfterPropertiesSet();
|
||||
schedulerFactoryObject.Start();
|
||||
await schedulerFactoryObject.Start();
|
||||
}
|
||||
finally
|
||||
{
|
||||
schedulerFactoryObject.Dispose();
|
||||
}
|
||||
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true, A<CancellationToken>._)).MustHaveHappened();
|
||||
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObjectWithPlainQuartzObjects()
|
||||
public async Task TestSchedulerFactoryObjectWithPlainQuartzObjects()
|
||||
{
|
||||
IJobFactory jobFactory = new AdaptableJobFactory();
|
||||
|
||||
@@ -456,8 +456,8 @@ namespace Spring.Scheduling.Quartz
|
||||
trigger1.RepeatInterval = TimeSpan.FromMilliseconds(20);
|
||||
|
||||
IScheduler scheduler = A.Fake<IScheduler>();
|
||||
A.CallTo(() => scheduler.GetTrigger(A<TriggerKey>._)).Returns(null);
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._)).Returns(null);
|
||||
A.CallTo(() => scheduler.GetTrigger(A<TriggerKey>._, A<CancellationToken>._)).Returns(Task.FromResult<ITrigger>(null));
|
||||
A.CallTo(() => scheduler.GetJobDetail(A<JobKey>._, A<CancellationToken>._)).Returns(Task.FromResult<IJobDetail>(null));
|
||||
|
||||
SchedulerFactoryObject schedulerFactoryObject = new TestSchedulerFactoryObject(scheduler);
|
||||
|
||||
@@ -467,7 +467,7 @@ namespace Spring.Scheduling.Quartz
|
||||
try
|
||||
{
|
||||
schedulerFactoryObject.AfterPropertiesSet();
|
||||
schedulerFactoryObject.Start();
|
||||
await schedulerFactoryObject.Start();
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -479,18 +479,18 @@ namespace Spring.Scheduling.Quartz
|
||||
.WhenArgumentsMatch(x => x.Get<IJobFactory>(0) == jobFactory)
|
||||
.MustHaveHappened();
|
||||
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail1, true, true)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetJobDetail(new JobKey("myJob0", SchedulerConstants.DefaultGroup))).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetJobDetail(new JobKey("myJob1", SchedulerConstants.DefaultGroup))).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup))).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup))).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail0, true, true, A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.AddJob(jobDetail1, true, true, A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetJobDetail(new JobKey("myJob0", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetJobDetail(new JobKey("myJob1", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger0", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).MustHaveHappened();
|
||||
A.CallTo(() => scheduler.GetTrigger(new TriggerKey("myTrigger1", SchedulerConstants.DefaultGroup), A<CancellationToken>._)).MustHaveHappened();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryObjectWithApplicationContext()
|
||||
public async Task TestSchedulerFactoryObjectWithApplicationContext()
|
||||
{
|
||||
TestObject tb = new TestObject("tb", 99);
|
||||
StaticApplicationContext ac = new StaticApplicationContext();
|
||||
@@ -509,7 +509,7 @@ namespace Spring.Scheduling.Quartz
|
||||
try
|
||||
{
|
||||
schedulerFactoryObject.AfterPropertiesSet();
|
||||
schedulerFactoryObject.Start();
|
||||
await schedulerFactoryObject.Start();
|
||||
IScheduler returnedScheduler = (IScheduler) schedulerFactoryObject.GetObject();
|
||||
Assert.AreEqual(tb, returnedScheduler.Context["testObject"]);
|
||||
Assert.AreEqual(ac, returnedScheduler.Context["appCtx"]);
|
||||
@@ -545,7 +545,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerWithTaskExecutor()
|
||||
public async Task TestSchedulerWithTaskExecutor()
|
||||
{
|
||||
CountingTaskExecutor taskExecutor = new CountingTaskExecutor();
|
||||
DummyJob.count = 0;
|
||||
@@ -567,7 +567,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factoryObject.Triggers = new ITrigger[] {trigger};
|
||||
factoryObject.JobDetails = new IJobDetail[] {jobDetail};
|
||||
factoryObject.AfterPropertiesSet();
|
||||
factoryObject.Start();
|
||||
await factoryObject.Start();
|
||||
|
||||
Thread.Sleep(500);
|
||||
Assert.IsTrue(DummyJob.count > 0);
|
||||
@@ -579,7 +579,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerWithRunnable()
|
||||
public async Task TestSchedulerWithRunnable()
|
||||
{
|
||||
DummyRunnable.count = 0;
|
||||
|
||||
@@ -599,7 +599,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factoryObject.Triggers = new ITrigger[] {trigger};
|
||||
factoryObject.JobDetails = new IJobDetail[] {jobDetail};
|
||||
factoryObject.AfterPropertiesSet();
|
||||
factoryObject.Start();
|
||||
await factoryObject.Start();
|
||||
|
||||
DummyRunnable.runEvent.WaitOne(500);
|
||||
Assert.IsTrue(DummyRunnable.count > 0);
|
||||
@@ -610,7 +610,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerWithQuartzJobObject()
|
||||
public async Task TestSchedulerWithQuartzJobObject()
|
||||
{
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
@@ -632,7 +632,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factoryObject.Triggers = new ITrigger[] {trigger};
|
||||
factoryObject.JobDetails = new IJobDetail[] {jobDetail};
|
||||
factoryObject.AfterPropertiesSet();
|
||||
factoryObject.Start();
|
||||
await factoryObject.Start();
|
||||
|
||||
Thread.Sleep(500);
|
||||
Assert.AreEqual(10, DummyJobObject.param);
|
||||
@@ -644,7 +644,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerWithSpringObjectJobFactory()
|
||||
public async Task TestSchedulerWithSpringObjectJobFactory()
|
||||
{
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
@@ -668,7 +668,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factoryObject.Triggers = new ITrigger[] {trigger};
|
||||
factoryObject.JobDetails = new IJobDetail[] {jobDetail};
|
||||
factoryObject.AfterPropertiesSet();
|
||||
factoryObject.Start();
|
||||
await factoryObject.Start();
|
||||
|
||||
Thread.Sleep(500);
|
||||
Assert.AreEqual(10, DummyJob.param);
|
||||
@@ -717,7 +717,7 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerWithSpringObjectJobFactoryAndRunnable()
|
||||
public async Task TestSchedulerWithSpringObjectJobFactoryAndRunnable()
|
||||
{
|
||||
DummyRunnable.param = 0;
|
||||
DummyRunnable.count = 0;
|
||||
@@ -740,7 +740,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factoryObject.Triggers = new ITrigger[] {trigger};
|
||||
factoryObject.JobDetails = new IJobDetail[] {jobDetail};
|
||||
factoryObject.AfterPropertiesSet();
|
||||
factoryObject.Start();
|
||||
await factoryObject.Start();
|
||||
|
||||
Thread.Sleep(500);
|
||||
Assert.AreEqual(10, DummyRunnable.param);
|
||||
@@ -752,7 +752,7 @@ namespace Spring.Scheduling.Quartz
|
||||
///<summary>
|
||||
///</summary>
|
||||
[Test]
|
||||
public void TestSchedulerWithSpringObjectJobFactoryAndQuartzJobObject()
|
||||
public async Task TestSchedulerWithSpringObjectJobFactoryAndQuartzJobObject()
|
||||
{
|
||||
DummyJobObject.param = 0;
|
||||
DummyJobObject.count = 0;
|
||||
@@ -775,7 +775,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factoryObject.Triggers = new ITrigger[] {trigger};
|
||||
factoryObject.JobDetails = new IJobDetail[] {jobDetail};
|
||||
factoryObject.AfterPropertiesSet();
|
||||
factoryObject.Start();
|
||||
await factoryObject.Start();
|
||||
|
||||
Thread.Sleep(500);
|
||||
Assert.AreEqual(10, DummyJobObject.param);
|
||||
@@ -788,7 +788,7 @@ namespace Spring.Scheduling.Quartz
|
||||
///
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerWithSpringObjectJobFactoryAndJobSchedulingData()
|
||||
public async Task TestSchedulerWithSpringObjectJobFactoryAndJobSchedulingData()
|
||||
{
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
@@ -798,7 +798,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factoryObject.JobSchedulingDataLocation = "job-scheduling-data.xml";
|
||||
// TODO bean.ResourceLoader = (new FileSystemResourceLoader());
|
||||
factoryObject.AfterPropertiesSet();
|
||||
factoryObject.Start();
|
||||
await factoryObject.Start();
|
||||
|
||||
Thread.Sleep(500);
|
||||
Assert.AreEqual(10, DummyJob.param);
|
||||
@@ -924,145 +924,14 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Tests how scheduler is exposed to application context.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerRepositoryExposure()
|
||||
public async Task TestSchedulerRepositoryExposure()
|
||||
{
|
||||
XmlApplicationContext ctx = new XmlApplicationContext("schedulerRepositoryExposure.xml");
|
||||
Assert.AreSame(SchedulerRepository.Instance.Lookup("myScheduler"), ctx.GetObject("scheduler"));
|
||||
var expected = await SchedulerRepository.Instance.Lookup("myScheduler");
|
||||
Assert.AreSame(expected, ctx.GetObject("scheduler"));
|
||||
ctx.Dispose();
|
||||
}
|
||||
|
||||
private class TestSchedulerListener : ISchedulerListener
|
||||
{
|
||||
public void JobScheduled(ITrigger trigger)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobUnscheduled(TriggerKey triggerKey)
|
||||
{
|
||||
}
|
||||
|
||||
public void TriggerFinalized(ITrigger trigger)
|
||||
{
|
||||
}
|
||||
|
||||
public void TriggerPaused(TriggerKey triggerKey)
|
||||
{
|
||||
}
|
||||
|
||||
public void TriggersPaused(string triggerGroup)
|
||||
{
|
||||
}
|
||||
|
||||
public void TriggerResumed(TriggerKey triggerKey)
|
||||
{
|
||||
}
|
||||
|
||||
public void TriggersResumed(string triggerGroup)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobAdded(IJobDetail jobDetail)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobDeleted(JobKey jobKey)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobPaused(JobKey jobKey)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobsPaused(string jobGroup)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobResumed(JobKey jobKey)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobsResumed(string jobGroup)
|
||||
{
|
||||
}
|
||||
|
||||
public void SchedulerError(string msg, SchedulerException cause)
|
||||
{
|
||||
}
|
||||
|
||||
public void SchedulerInStandbyMode()
|
||||
{
|
||||
}
|
||||
|
||||
public void SchedulerStarted()
|
||||
{
|
||||
}
|
||||
|
||||
public void SchedulerStarting()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SchedulerShutdown()
|
||||
{
|
||||
}
|
||||
|
||||
public void SchedulerShuttingdown()
|
||||
{
|
||||
}
|
||||
|
||||
public void SchedulingDataCleared()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestJobListener : IJobListener
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void JobToBeExecuted(IJobExecutionContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobExecutionVetoed(IJobExecutionContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class TestTriggerListener : ITriggerListener
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void TriggerFired(ITrigger trigger, IJobExecutionContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public bool VetoJobExecution(ITrigger trigger, IJobExecutionContext context)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void TriggerMisfired(ITrigger trigger)
|
||||
{
|
||||
}
|
||||
|
||||
public void TriggerComplete(ITrigger trigger, IJobExecutionContext context,
|
||||
SchedulerInstruction triggerInstructionCode)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Simple task executor that tracks invocation count.
|
||||
/// </summary>
|
||||
@@ -1107,9 +976,10 @@ namespace Spring.Scheduling.Quartz
|
||||
/// applied as object property values by execute. The contract is
|
||||
/// exactly the same as for the standard Quartz execute method.
|
||||
/// </summary>
|
||||
protected override void ExecuteInternal(IJobExecutionContext jobExecutionContext)
|
||||
protected override Task ExecuteInternal(IJobExecutionContext jobExecutionContext)
|
||||
{
|
||||
count++;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1125,10 +995,11 @@ namespace Spring.Scheduling.Quartz
|
||||
/// <summary>
|
||||
/// Runs thread runnable.
|
||||
/// </summary>
|
||||
public void Run()
|
||||
public Task Run()
|
||||
{
|
||||
count++;
|
||||
runEvent.Set();
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1158,9 +1029,10 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Executes this job instance.
|
||||
///</summary>
|
||||
///<param name="jobExecutionContext"></param>
|
||||
public void Execute(IJobExecutionContext jobExecutionContext)
|
||||
public Task Execute(IJobExecutionContext jobExecutionContext)
|
||||
{
|
||||
count++;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FakeItEasy;
|
||||
|
||||
using NUnit.Framework;
|
||||
@@ -87,7 +88,7 @@ namespace Spring.Scheduling.Quartz
|
||||
factory.AutoStartup = false;
|
||||
factory.AfterPropertiesSet();
|
||||
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.Start()).MustNotHaveHappened();
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.Start(A<CancellationToken>._)).MustNotHaveHappened();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -106,7 +107,7 @@ namespace Spring.Scheduling.Quartz
|
||||
|
||||
factory.AfterPropertiesSet();
|
||||
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.AddCalendar(calendarName, cal, true, true)).MustHaveHappened();
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.AddCalendar(calendarName, cal, true, true, A<CancellationToken>._)).MustHaveHappened();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -122,7 +123,7 @@ namespace Spring.Scheduling.Quartz
|
||||
SimpleTriggerImpl trigger = new SimpleTriggerImpl(TRIGGER_NAME, TRIGGER_GROUP);
|
||||
factory.Triggers = new ITrigger[] { trigger };
|
||||
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.GetTrigger(new TriggerKey(TRIGGER_NAME, TRIGGER_GROUP))).Returns(trigger);
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.GetTrigger(new TriggerKey(TRIGGER_NAME, TRIGGER_GROUP), A<CancellationToken>._)).Returns(trigger);
|
||||
|
||||
factory.AfterPropertiesSet();
|
||||
}
|
||||
@@ -134,7 +135,7 @@ namespace Spring.Scheduling.Quartz
|
||||
public void TestAfterPropertiesSet_Trigger_TriggerDoesntExist()
|
||||
{
|
||||
InitForAfterPropertiesSetTest();
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.GetTrigger(A<TriggerKey>._)).Returns(null);
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.GetTrigger(A<TriggerKey>._, A<CancellationToken>._)).Returns(Task.FromResult<ITrigger>(null));
|
||||
|
||||
const string TRIGGER_NAME = "trigName";
|
||||
const string TRIGGER_GROUP = "trigGroup";
|
||||
@@ -143,7 +144,7 @@ namespace Spring.Scheduling.Quartz
|
||||
|
||||
factory.AfterPropertiesSet();
|
||||
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.ScheduleJob(trigger)).MustHaveHappened();
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.ScheduleJob(trigger, A<CancellationToken>._)).MustHaveHappened();
|
||||
}
|
||||
|
||||
|
||||
@@ -159,38 +160,38 @@ namespace Spring.Scheduling.Quartz
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestStart()
|
||||
public async Task TestStart()
|
||||
{
|
||||
factory.SchedulerFactoryType = typeof(TestSchedulerFactory);
|
||||
factory.AutoStartup = false;
|
||||
factory.AfterPropertiesSet();
|
||||
factory.Start();
|
||||
await factory.Start();
|
||||
|
||||
A.CallTo(TestSchedulerFactory.MockScheduler)
|
||||
.Where(x => x.Method.Name.Equals("set_JobFactory"))
|
||||
.WhenArgumentsMatch(x => x.Get<IJobFactory>(0) != null)
|
||||
.MustHaveHappened();
|
||||
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.Start()).MustHaveHappened();
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.Start(A<CancellationToken>._)).MustHaveHappened();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestStop()
|
||||
public async Task TestStop()
|
||||
{
|
||||
factory.SchedulerFactoryType = typeof(TestSchedulerFactory);
|
||||
factory.AutoStartup = false;
|
||||
factory.AfterPropertiesSet();
|
||||
factory.Stop();
|
||||
await factory.Stop();
|
||||
|
||||
A.CallTo(TestSchedulerFactory.MockScheduler)
|
||||
.Where(x => x.Method.Name.Equals("set_JobFactory"))
|
||||
.WhenArgumentsMatch(x => x.Get<IJobFactory>(0) != null)
|
||||
.MustHaveHappened();
|
||||
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.Standby()).MustHaveHappened();
|
||||
A.CallTo(() => TestSchedulerFactory.MockScheduler.Standby(A<CancellationToken>._)).MustHaveHappened();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -284,34 +285,23 @@ ConnectionStringKey+ " = " + ConnectionStringValue + Environment.NewLine +
|
||||
/// <summary>
|
||||
/// The mocked scheduler.
|
||||
/// </summary>
|
||||
public static IScheduler MockScheduler
|
||||
public static IScheduler MockScheduler => mockScheduler;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IScheduler> GetScheduler(CancellationToken _)
|
||||
{
|
||||
get { return mockScheduler; }
|
||||
return Task.FromResult(mockScheduler);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///</summary>
|
||||
///<returns></returns>
|
||||
public IScheduler GetScheduler()
|
||||
/// <inheritdoc />
|
||||
public Task<IScheduler> GetScheduler(string schedName, CancellationToken _)
|
||||
{
|
||||
return mockScheduler;
|
||||
return Task.FromResult(mockScheduler);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///</summary>
|
||||
///<param name="schedName"></param>
|
||||
///<returns></returns>
|
||||
public IScheduler GetScheduler(string schedName)
|
||||
{
|
||||
return mockScheduler;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///</summary>
|
||||
public ICollection<IScheduler> AllSchedulers
|
||||
{
|
||||
get { return new List<IScheduler>(); }
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public Task<IReadOnlyList<IScheduler>> GetAllSchedulers(CancellationToken _)
|
||||
=> Task.FromResult<IReadOnlyList<IScheduler>>(new List<IScheduler>());
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
@@ -326,21 +316,15 @@ ConnectionStringKey+ " = " + ConnectionStringValue + Environment.NewLine +
|
||||
{
|
||||
private NameValueCollection properties;
|
||||
|
||||
///<summary>
|
||||
/// Initializes the factory.
|
||||
///</summary>
|
||||
///<param name="props"></param>
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(NameValueCollection props)
|
||||
{
|
||||
this.properties = props;
|
||||
properties = props;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return propeties given to this factory at initialization time.
|
||||
/// </summary>
|
||||
public NameValueCollection Properties
|
||||
{
|
||||
get { return properties; }
|
||||
}
|
||||
public NameValueCollection Properties => properties;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz.Impl;
|
||||
using Quartz.Job;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl.Triggers;
|
||||
using Quartz.Job;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
@@ -95,31 +94,28 @@ namespace Spring.Scheduling.Quartz
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class NoOpJob : IJob
|
||||
{
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test job object that has injectable properties
|
||||
/// </summary>
|
||||
public class InjectableJob : NoOpJob
|
||||
{
|
||||
private int number;
|
||||
private string foo;
|
||||
|
||||
/// <summary>
|
||||
/// Simple int property.
|
||||
/// </summary>
|
||||
public int Number
|
||||
{
|
||||
get { return number; }
|
||||
set { number = value; }
|
||||
}
|
||||
public int Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Simple string property.
|
||||
/// </summary>
|
||||
public string Foo
|
||||
{
|
||||
get { return foo; }
|
||||
set { foo = value; }
|
||||
}
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ namespace Spring.Scheduling.Quartz
|
||||
public static TriggerFiredBundle CreateMinimalFiredBundleWithTypedJobDetail(Type jobType, IOperableTrigger trigger)
|
||||
{
|
||||
IJobDetail jd = new JobDetailImpl("jobName", "jobGroup", jobType);
|
||||
TriggerFiredBundle bundle = new TriggerFiredBundle(jd, trigger, null, false, null, null, null, null);
|
||||
TriggerFiredBundle bundle = new TriggerFiredBundle(jd, trigger, null, false, DateTimeOffset.UtcNow, null, null, null);
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net452</TargetFramework>
|
||||
<TargetFrameworks>netcoreapp2.1;$(TargetFullFrameworkVersion)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Scheduling.Quartz2\Spring.Scheduling.Quartz2.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Scheduling.Quartz3\Spring.Scheduling.Quartz3.csproj" />
|
||||
<ProjectReference Include="..\Spring.Core.Tests\Spring.Core.Tests.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -13,7 +13,7 @@
|
||||
<job>
|
||||
<name>myJob</name>
|
||||
<group>myGroup</group>
|
||||
<job-type>Spring.Scheduling.Quartz.DummyJob, Spring.Scheduling.Quartz2.Tests</job-type>
|
||||
<job-type>Spring.Scheduling.Quartz.DummyJob, Spring.Scheduling.Quartz3.Tests</job-type>
|
||||
<durable>true</durable>
|
||||
<recover>false</recover>
|
||||
<job-data-map>
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
|
||||
|
||||
<object id="scheduler" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object id="scheduler" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="Triggers">
|
||||
<list>
|
||||
<ref local="exportTrigger"/>
|
||||
@@ -14,9 +14,9 @@
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id="exportTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="exportTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<property name="JobDetail">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="TargetObject" ref="exportService"/>
|
||||
<property name="TargetMethod" value="DoExport"/>
|
||||
</object>
|
||||
@@ -26,9 +26,9 @@
|
||||
<property name="RepeatCount" value="1"/>
|
||||
</object>
|
||||
|
||||
<object id="importTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="importTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<property name="JobDetail">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="TargetObject" ref="importService"/>
|
||||
|
||||
<property name="TargetMethod" value="DoImport"/>
|
||||
@@ -38,8 +38,8 @@
|
||||
<property name="RepeatCount" value="1"/>
|
||||
</object>
|
||||
|
||||
<object id="exportService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz2.Tests"/>
|
||||
<object id="exportService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz3.Tests"/>
|
||||
|
||||
<object id="importService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz2.Tests"/>
|
||||
<object id="importService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz3.Tests"/>
|
||||
|
||||
</objects>
|
||||
@@ -5,11 +5,11 @@
|
||||
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
|
||||
|
||||
|
||||
<object id="scheduler1" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object id="scheduler1" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="SchedulerName" value="quartz1"/>
|
||||
</object>
|
||||
|
||||
<object id="scheduler2" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object id="scheduler2" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="SchedulerName" value="quartz2"/>
|
||||
</object>
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
|
||||
|
||||
|
||||
<object id="scheduler" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz2"/>
|
||||
<object id="scheduler" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz3"/>
|
||||
|
||||
<object type="Spring.Scheduling.Quartz.SchedulerAccessorObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.SchedulerAccessorObject, Spring.Scheduling.Quartz3">
|
||||
<property name="Scheduler" ref="scheduler"/>
|
||||
<property name="Triggers">
|
||||
<list>
|
||||
@@ -18,9 +18,9 @@
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id="exportTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="exportTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<property name="JobDetail">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="TargetObject" ref="exportService"/>
|
||||
<property name="TargetMethod" value="DoExport"/>
|
||||
</object>
|
||||
@@ -29,10 +29,10 @@
|
||||
<property name="RepeatCount" value="1"/>
|
||||
</object>
|
||||
|
||||
<object id="importTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="importTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<property name="jobDetail">
|
||||
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="TargetObject" ref="importService"/>
|
||||
<property name="TargetMethod" value="DoImport"/>
|
||||
</object>
|
||||
@@ -41,8 +41,8 @@
|
||||
<property name="RepeatCount" value="1"/>
|
||||
</object>
|
||||
|
||||
<object id="exportService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz2.Tests"/>
|
||||
<object id="exportService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz3.Tests"/>
|
||||
|
||||
<object id="importService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz2.Tests"/>
|
||||
<object id="importService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz3.Tests"/>
|
||||
|
||||
</objects>
|
||||
@@ -5,12 +5,12 @@
|
||||
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
|
||||
|
||||
|
||||
<object id="scheduler" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object id="scheduler" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="schedulerName" value="myScheduler"/>
|
||||
<property name="exposeSchedulerInRepository" value="true"/>
|
||||
</object>
|
||||
|
||||
<object type="Spring.Scheduling.Quartz.SchedulerAccessorObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.SchedulerAccessorObject, Spring.Scheduling.Quartz3">
|
||||
<property name="schedulerName" value="myScheduler"/>
|
||||
|
||||
<property name="triggers">
|
||||
@@ -21,10 +21,10 @@
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id="exportTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="exportTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
|
||||
<property name="JobDetail">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="TargetObject" ref="exportService"/>
|
||||
<property name="TargetMethod" value="DoExport"/>
|
||||
</object>
|
||||
@@ -33,9 +33,9 @@
|
||||
<property name="RepeatCount" value="1"/>
|
||||
</object>
|
||||
|
||||
<object id="importTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz2">
|
||||
<object id="importTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz3">
|
||||
<property name="jobDetail">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz2">
|
||||
<object type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz3">
|
||||
<property name="TargetObject" ref="importService"/>
|
||||
<property name="TargetMethod" value="DoImport"/>
|
||||
</object>
|
||||
@@ -45,8 +45,8 @@
|
||||
<property name="RepeatCount" value="1"/>
|
||||
</object>
|
||||
|
||||
<object id="exportService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz2.Tests"/>
|
||||
<object id="exportService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz3.Tests"/>
|
||||
|
||||
<object id="importService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz2.Tests"/>
|
||||
<object id="importService" type="Spring.Scheduling.Quartz.QuartzTestObject, Spring.Scheduling.Quartz3.Tests"/>
|
||||
|
||||
</objects>
|
||||
Reference in New Issue
Block a user