janetsmith
janetsmith

Reputation: 8722

How to pass instance variables into Quartz job?

I wonder how to pass an instance variable externally in Quartz?

Below is pseudo code I would like to write. How can I pass externalInstance into this Job?

public class SimpleJob implements Job {
        @Override
        public void execute(JobExecutionContext context)
                throws JobExecutionException {

            float avg = externalInstance.calculateAvg();
        }
}

Upvotes: 31

Views: 53235

Answers (7)

Anthony Vinay
Anthony Vinay

Reputation: 647

Just do the following :

public class NightlyJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap mergedJobDataMap = context.getMergedJobDataMap();
        String orgCode = mergedJobDataMap.getString("dataName");
        System.out.println(MessageFormat.format("Nightly Job {0}", orgCode));
    }

}

Upvotes: 0

Mohammed Elrashidy
Mohammed Elrashidy

Reputation: 1871

Quartz has a simple way to grep params from JobDataMap using setters

I am using Quartz 2.3 and I simply used setter to fetch passed instance objects

For example I created this class

public class Data implements Serializable {
    @JsonProperty("text")
    private String text;

    @JsonCreator
    public Data(@JsonProperty("b") String text) {this.text = text;}

    public String getText() {return text;}
}

Then I created an instance of this class and put it inside the JobDataMap

JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("data", new Data(1, "One!"));
JobDetail job = newJob(HelloJob.class)
                .withIdentity("myJob", "group")
                .withDescription("bla bla bla")
                .usingJobData(jobDataMap) // <!!!
                .build();

And my job class looks like this

public class HelloJob implements Job {
    Data data;

    public HelloJob() {}

    public void execute(JobExecutionContext context)
            throws JobExecutionException
    {
        String text = data.getText();
        System.out.println(text);
    }

    public void setData(Data data) {this.data = data;}
}
  • Note: it is mandatory that the field and the setter matched the key

This code will print One! when you schedule the job.

That's it, clean and efficient

Upvotes: 2

Evvo
Evvo

Reputation: 499

Add the object to the JobDataMap:

JobDetail job = JobBuilder.newJob(MyJobClass.class)
                          .withIdentity("MyIdentity",
                                        "MyGroup")
                          .build();
job.getJobDataMap()
   .put("MyObject",
        myObject);

Access the data from the JobDataMap:

var myObject = (MyObjectClass) context.getJobDetail()
                                      .getJobDataMap()
                                      .get("carrier");

Upvotes: 4

Rips
Rips

Reputation: 2004

you can put your instance in the schedulerContext.When you are going to schedule the job ,just before that you can do below:

getScheduler().getContext().put("externalInstance", externalInstance);

Your job class would be like below:

public class SimpleJob implements Job {
    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        SchedulerContext schedulerContext = null;
        try {
            schedulerContext = context.getScheduler().getContext();
        } catch (SchedulerException e1) {
            e1.printStackTrace();
        }
        ExternalInstance externalInstance =
            (ExternalInstance) schedulerContext.get("externalInstance");

        float avg = externalInstance.calculateAvg();
    }
}

If you are using Spring ,you can actually using spring's support to inject the whole applicationContext like answered in the Link

Upvotes: 62

Harsh Maheswari
Harsh Maheswari

Reputation: 507

Solve this problem by creating one interface with one HashMap putting required information there.

Implement this interface in your Quartz Job class this information will be accessible.

In IFace

Map<JobKey,Object> map = new HashMap<>();

In Job

map.get(context.getJobDetail().getKey()) =>  will give you Object

Upvotes: 2

Matthew
Matthew

Reputation: 11347

This is the responsibility of the JobFactory. The default PropertySettingJobFactory implementation will invoke any bean-setter methods, based on properties found in the schdeuler context, the trigger, and the job detail. So as long as you have implemnted an appropriate setContext() setter method you should be able to do any of the following:

scheduler.getContext().put("context", context);

Or

Trigger trigger = TriggerBuilder.newTrigger()
  ...
  .usingJobData("context", context)
  .build()

Or

JobDetail job = JobBuilder.newJob(SimpleJob.class)
  ...
  .usingJobData("context", context)
  .build()

Or if that isn't enough you can provide your own JobFactory class which instantiates the Job objects however you please.

Upvotes: 0

Vikdor
Vikdor

Reputation: 24124

While scheduling the job using a trigger, you would have defined JobDataMap that is added to the JobDetail. That JobDetail object will be present in the JobExecutionContext passed to the execute() method in your Job. So, you should figure out a way to pass your externalInstance through the JobDataMap. HTH.

Upvotes: 11

Related Questions