Quartz Scheduler: How to pass custom objects as JobParameter?
Asked Answered
A

5

23

I am planning to write a ASP.NET page to trigger the job on demand. Currently, I am using SimpleTrigger class to trigger the job but none of the __Trigger class supports object type as value in JobParameters and it has come to my knowledge that WCF Tcp binding is used under the hook to pass the parameters to job scheduling engine. I would like to know how to pass custom object (serializable) as job parameters. Thanks for your advice!

Ammunition answered 21/8, 2011 at 11:24 Comment(0)
A
53

There are two ways to pass an object that can be retrieved when a Quartz job executes:

Pass the instance in the data map. When you set the job up, add your instance to the map with a key like this:

// Create job etc...
var MyClass _myInstance;
statusJob.JobDataMap.Put("myKey", _myInstance);
// Schedule job...

Retrieve the instance in the job's Execute() method like this:

public void Execute(IJobExecutionContext context)
        {
            var dataMap = context.MergedJobDataMap;
            var myInstance = (MyClass)dataMap["myKey"];

OR

Add the instance to the scheduler context when you set the job up, like this:

  ISchedulerFactory schedFact = new StdSchedulerFactory();
  _sched = schedFact.GetScheduler();
  _sched.Start();
  // Create job etc...
  var MyClass _myInstance;
  _sched.Context.Put("myKey", myInstance);
  // Schedule job...

Retrieve the instance in the job's Execute() method like this:

public void Execute(IJobExecutionContext context)
        {
            var schedulerContext = context.Scheduler.Context;
            var myInstance = (MyClass)schedulerContext.Get("myKey");
Arie answered 4/9, 2014 at 8:35 Comment(3)
When using the JobDataMap, how is the MyClass instance being serialized? Does it need to be attributed with [Serializable]?Hydrus
Dejan, I have not used [Serializable], and my instances are retrieved OK. As far as I can tell, the serialization is invoked when you use a persistant JobStore in Quartz. Note that the Quartz documention warns against storing non-primitive types if serializing: quartz-scheduler.org/documentation/best-practices. On that basis the example in my answer may not be useful to you.Arie
This works surprisingly well. I was able to pass an MQTTNet client instance to jobs! Great!Gian
H
7

I was having unexpected results with hillstuk's answer above in multithreaded environments. Here's my solution using Newtonsoft… Enjoy

public void InitJob() {

    MyClass data = new MyClass {Foo = “Foo fighters”}; 

    /* a unique identifier for demonstration purposes.. Use your own concoction here. */
    int uniqueIdentifier = new Random().Next(int.MinValue, int.MaxValue); 

    IJobDetail newJob = JobBuilder.Create<MyAwesomeJob>()
    .UsingJobData("JobData", JsonConvert.SerializeObject(data))
    .WithIdentity($"job-{uniqueIdentifier}", "main")                
    .Build();

}

/* the execute method */
public class MyAwesomeJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {                   
        var jobData = JsonConvert.DeserializeObject<MyClass>(context.JobDetail.JobDataMap.GetString("JobData"));    
    }
}

/* for completeness */
public class MyClass {
    string Foo { get; set; } 
}
Hamal answered 28/12, 2016 at 7:50 Comment(0)
T
5

When you schedule a job you can set a JobDataMap on the JobDetail object and pass this to your scheduler, there are some limitations described in the quartz.net tutorial. The job can access the data via:

JobDataMap dataMap = context.JobDetail.JobDataMap;

However I prefer to access my job configuration, via an repository injected into the job.

Tevet answered 29/8, 2011 at 12:58 Comment(3)
Thanks for your reply but what I am looking for is how to pass the objects from external application.Ammunition
This is something I also need to know ... still searchingNavy
How do you inject your repository without using the JobDataMap? Or is it only the repo that you inject?Doldrums
N
4

You can put your instance/object in the IJobDetail.

 JobDataMap m = new JobDataMap();
  m.Put("Class1", new Class1(){name="xxx"});


  IJobDetail job = JobBuilder.Create<Job>()
            .WithIdentity("myJob", "group1")
            .UsingJobData(m)//class object
            .UsingJobData("name2", "Hello World!")
            .Build();

usage

  public void Execute(IJobExecutionContext context)
        {
 JobDataMap dataMap = context.JobDetail.JobDataMap;
            Class1 class1 = (Class1)dataMap.Get("Class1");
string x = class1.name;
}
Najera answered 16/8, 2017 at 19:39 Comment(0)
K
1

I passed the object following way

JobDetail job1 = JobBuilder.newJob(JobAutomation.class)
                .usingJobData("path", path)
                .withIdentity("job2", "group2").build();

        CronTrigger trigger1 = TriggerBuilder.newTrigger()
                .withIdentity("cronTrigger2", "group2")
                .withSchedule(CronScheduleBuilder.cronSchedule("40 27 11 * * ?"))
                .build();

get jobdatamap by following lines of code

JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String path =dataMap.getString("path");
Knowledge answered 13/6, 2018 at 18:11 Comment(1)
JobDataMap dataMap = context.getMergedJobDataMap(); is preferableMisdemean

© 2022 - 2024 — McMap. All rights reserved.