Quartz.net: How to create jobs using Dependency Injection
Asked Answered
A

1

10

I am trying to execute a Quartz scheduler job in .NET with a non-empty constructor and I try to use the default Dependency Injection of .NET to supply the dependencies. This is my job class which needs a dependency injection

public class MyJob : IJob 
{
    private readonly ILogger _logger;

    public MyJob(ILogger<MyJob> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));  
    }

    public Task Execute(IJobExecutionContext context)
    {
        _logger.LogDebug("It's working!");
    }
}

And this is how I build the job

IJobDetail jobDetail = JobBuilder.Create<MyJob>()
    .WithIdentity("MyID", "MyGroup")
    .Build();

var triggerBuilder = TriggerBuilder.Create()
    .WithIdentity("MyID")
    .StartAt(DateTime.Now)
    .WithCronSchedule("*/1 * * * * ?"); // Every second

var trigger = triggerBuilder.Build();
_scheduler.ScheduleJob(jobDetail, trigger)

Now, I have defined in my app configuration the following:

// Quartz configuration.
services.AddQuartz(q =>
{
    // Add dependency injection.
    q.UseMicrosoftDependencyInjectionScopedJobFactory(options =>
    {
        // if we don't have the job in DI, allow fallback
        // to configure via default constructor
        options.AllowDefaultConstructor = true;
    });
});

services.AddTransient<MyJob>();
// Also tried services.AddTransient<IJob, MyJob>();

as defined in the documentation on DI. Yet when I rebuild my solution and run the server, the following error is thrown:

Quartz.SchedulerException: Problem instantiating class 'MyProject.MyNamespace.Myjob: Cannot instantiate type which has no empty constructor Parameter name: MyJob' ---> System.ArgumentException: Cannot instantiate type which has no empty constructor

Yet, I explicitly setup MS DI for Quartz to use following their documentation. So how can I inject dependencies? I am using Quartz 3.2.4 and I installed the Quartz.Extensions.DependencyInjection package (also 3.2.4).

Apace answered 19/3, 2021 at 15:17 Comment(0)
U
3

You should register your jobs and triggers within the AddQuartz. If you look at the official documentation you will see that the ScheduleJob/AddJob/AddTrigger calls are done within the callback which ensures that the DI works. This will probably change in 3.3 version and the job registration won't be that strict anymore.

Untimely answered 20/3, 2021 at 16:20 Comment(2)
How do you know that it will be updated in version 3.3?Apace
This PR changed the job instantiation to happen without resolving from the container. Triggers still need to be inside AddQuartz() if you want them to be registered against the configured scheduler (you can resolve the scheduler and then add triggers of course).Untimely

© 2022 - 2024 — McMap. All rights reserved.