Skip to content

Commit

Permalink
Support injecting dependencies to XMLSchedulingDataProcessorPlugin (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma authored Nov 18, 2023
1 parent a5ec03c commit 9617757
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 12 deletions.
3 changes: 2 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* `TryGetString` method added to JobDataMap (#2125)
* Add NET 8.0 targeting for examples, tests and integration projects (#2192)
* Upgrade TimeZoneConverter to version 6.1.0 (#2194)
* Improve trimming compatibility #2195
* Improve trimming compatibility (#2195)

* FIXES
* JobDataMap `TryGetXXX` methods will now correctly return true/false if a key value can be retrieved (or not) (#2125)
Expand All @@ -17,6 +17,7 @@
* DailyCalendar should use same time zone offset for all checks (#2113)
* SendMailJob will now throw JobExecutionException on BuildMessage construction failure due to missing mandatory params. (#2126)
* JobInterruptMonitorPlugin should tolerate missing JobDataMapKeyAutoInterruptable (#2191)
* XMLSchedulingDataProcessorPlugin not using custom TypeLoader #2131


## Release 3.7.0, Aug 4 2023
Expand Down
27 changes: 27 additions & 0 deletions src/Quartz.Examples.AspNetCore/CustomTypeLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;

using Microsoft.Extensions.Logging;

using Quartz.Spi;

namespace Quartz.Examples.AspNetCore;

public class CustomTypeLoader : ITypeLoadHelper
{
private readonly ILogger<CustomTypeLoader> logger;

public CustomTypeLoader(ILogger<CustomTypeLoader> logger)
{
this.logger = logger;
}

public void Initialize()
{
}

public Type? LoadType(string? name)
{
logger.LogInformation("Requested to load type {TypeName}", name);
return Type.GetType(name!);
}
}
3 changes: 3 additions & 0 deletions src/Quartz.Examples.AspNetCore/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ public void ConfigureServices(IServiceCollection services)
q.UseInMemoryStore();
q.UseDefaultThreadPool(maxConcurrency: 10);

// you could use custom too
q.UseTypeLoader<CustomTypeLoader>();

// quickest way to create a job with single trigger is to use ScheduleJob
q.ScheduleJob<ExampleJob>(trigger => trigger
.WithIdentity("Combined Configuration Trigger")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Quartz
{
internal sealed class ServiceCollectionQuartzConfigurator : IServiceCollectionQuartzConfigurator
internal sealed class ServiceCollectionQuartzConfigurator : IServiceCollectionQuartzConfigurator, IContainerConfigurationSupport
{
private readonly IServiceCollection services;
private readonly SchedulerBuilder schedulerBuilder;
Expand Down Expand Up @@ -257,5 +257,18 @@ public void AddTriggerListener<
services.AddSingleton(new TriggerListenerConfiguration(typeof(T), matchers));
services.AddSingleton<ITriggerListener>(implementationFactory);
}

public void RegisterSingleton<
TService,
#if NET6_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
TImplementation>()
where TService : class
where TImplementation : class, TService
{

services.AddSingleton<TService, TImplementation>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,26 @@ public class XMLSchedulingDataProcessorPlugin : ISchedulerPlugin, IFileScanListe
/// <summary>
/// Initializes a new instance of the <see cref="XMLSchedulingDataProcessorPlugin"/> class.
/// </summary>
public XMLSchedulingDataProcessorPlugin()
public XMLSchedulingDataProcessorPlugin() : this(new SimpleTypeLoadHelper())
{
Log = LogProvider.GetLogger(typeof (XMLSchedulingDataProcessorPlugin));
}

/// <summary>
/// Gets the log.
/// Initializes a new instance of the <see cref="XMLSchedulingDataProcessorPlugin"/> class.
/// </summary>
/// <value>The log.</value>
public XMLSchedulingDataProcessorPlugin(ITypeLoadHelper typeLoadHelper)
{
Log = LogProvider.GetLogger(typeof (XMLSchedulingDataProcessorPlugin));
TypeLoadHelper = typeLoadHelper;
}

private ILog Log { get; }

public string Name { get; private set; } = null!;

public IScheduler Scheduler { get; private set; } = null!;

protected ITypeLoadHelper TypeLoadHelper { get; private set; } = null!;
protected ITypeLoadHelper TypeLoadHelper { get; private set; }

/// <summary>
/// Comma separated list of file names (with paths) to the XML files that should be read.
Expand Down Expand Up @@ -131,8 +135,6 @@ public virtual async Task Initialize(
{
Name = pluginName;
Scheduler = scheduler;
TypeLoadHelper = new SimpleTypeLoadHelper();
TypeLoadHelper.Initialize();

Log.Info("Registering Quartz Job Initialization Plug-in.");

Expand Down
20 changes: 18 additions & 2 deletions src/Quartz.Plugins/PluginConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@ namespace Quartz
{
public static class PluginConfigurationExtensions
{
public static T UseXmlSchedulingConfiguration<T>(
public static T UseXmlSchedulingConfiguration<
#if NET6_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
T>(
this T configurer,
Action<XmlSchedulingOptions> configure) where T : IPropertyConfigurationRoot
{
if (configurer is IContainerConfigurationSupport containerConfigurationSupport)
{
containerConfigurationSupport.RegisterSingleton<XMLSchedulingDataProcessorPlugin, XMLSchedulingDataProcessorPlugin>();
}
configurer.SetProperty("quartz.plugin.xml.type", typeof(XMLSchedulingDataProcessorPlugin).AssemblyQualifiedNameWithoutVersion());
configure.Invoke(new XmlSchedulingOptions(configurer));
return configurer;
Expand All @@ -21,10 +29,18 @@ public static T UseXmlSchedulingConfiguration<T>(
/// <summary>
/// Configures <see cref="JobInterruptMonitorPlugin "/> into use.
/// </summary>
public static T UseJobAutoInterrupt<T>(
public static T UseJobAutoInterrupt<
#if NET6_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
T>(
this T configurer,
Action<JobAutoInterruptOptions>? configure = null) where T : IPropertyConfigurationRoot
{
if (configurer is IContainerConfigurationSupport containerConfigurationSupport)
{
containerConfigurationSupport.RegisterSingleton<JobInterruptMonitorPlugin, JobInterruptMonitorPlugin>();
}
configurer.SetProperty("quartz.plugin.jobAutoInterrupt.type", typeof(JobInterruptMonitorPlugin).AssemblyQualifiedNameWithoutVersion());
configure?.Invoke(new JobAutoInterruptOptions(configurer));
return configurer;
Expand Down
12 changes: 12 additions & 0 deletions src/Quartz/IPropertyConfigurer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,16 @@ public interface IPropertySetter
public interface IPropertyConfigurationRoot : IPropertySetter
{
}

internal interface IContainerConfigurationSupport : IPropertyConfigurer, IPropertyConfigurationRoot
{
void RegisterSingleton<
TService,
#if NET6_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
TImplementation>()
where TService : class
where TImplementation : class, TService;
}
}
5 changes: 4 additions & 1 deletion src/Quartz/Impl/StdSchedulerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,10 @@ private async Task<IScheduler> Instantiate()
ISchedulerPlugin plugin;
try
{
plugin = InstantiateType<ISchedulerPlugin>(LoadType(plugInType));
var pluginTypeType = LoadType(plugInType) ?? throw new ConfigurationException($"Could not load plugin type {plugInType}");
// we need to use concrete types to resolve correct one
var method = GetType().GetMethod(nameof(InstantiateType), BindingFlags.Instance | BindingFlags.NonPublic)!.MakeGenericMethod(pluginTypeType);
plugin = (ISchedulerPlugin) method.Invoke(this, new [] { pluginTypeType })!;
}
catch (Exception e)
{
Expand Down

0 comments on commit 9617757

Please sign in to comment.