Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass data to a method being run as a MethodInvokingJobDetailFactoryBean?

What I'm really trying to do is create a Quartz job that doesn't run concurrently, but also can access the JobExecutionContext in order to get the previousFireTime. Here's my object:

// imports...

public class UtilityObject {

    private SomeService someService;

    @Autowired
    public UtilityObject(SomeService someService) {
        this.someService = someService;
    }

    public void execute(JobExecutionContext ctx) throws JobExecutionException {
        Date prevDate = ctx.getPreviousFireTime();

        // rest of the code...
    }
}

And here's how I've configured my bean:

<bean name="utilityBean" class="UtilityObject" />

<bean id="utilityJob"
    class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
   <property name="targetOjbect" ref="utilityBean" />
   <property name="targetMethod" value="execute" />
   <property name="concurrent" value="false" />
</bean>

<bean name="utilityTrigger"
    class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail" ref="utilityJob" />
    <property name="startDelay" value="5000" />
    <property name="repeatInterval" value="20000" />
</bean>

When I try to run this, it fails during the creation of the bean with

NoSuchMethodException: UtilityJob.execute()

Any ideas?

Solution:

After reading skaffman's answer, I was able to get my solution working. Using the trigger that I had, I knew that the name was, and figured out that the default group was 'DEFAULT'. I had my class extend the QuartzJobBean class, and then added this bit of code:

protected void executeInternal(JobExecutionContext ctx) 
               throws JobExecutionException {
    boolean isRunning = 
           (ctx.getScheduler().getTriggerState("utilityTrigger", "DEFAULT") ==
               Trigger.STATE_BLOCKED);

    if (isRunning) {
        // run the job
    }
} 

Sorry for the weird formatting; these are some long lines!

like image 554
Pat Avatar asked Dec 10 '22 09:12

Pat


2 Answers

It is possible to pass arguments to MethodInvokingJobDetailFactoryBean in the same way as with a spring MethodInvokingFactoryBean using the arguments property.

For example:

<bean id="myJob"
      class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="myBean" />
    <property name="targetMethod" value="myMethod" />
    <property name="arguments">
        <list>
            <value>greetings</value>
            <ref bean="anotherBean"/>
        </list>
    </property>
</bean>
like image 66
darrenmc Avatar answered Dec 13 '22 23:12

darrenmc


MethodInvokingJobDetailFactoryBean is handy, but primitive - it can only execute public methods with no arguments.

If your job needs access to the Quartz API, then you'll need to use JobDetailBean and QuartzJobBean instead of MethodInvokingJobDetailFactoryBean. See docs for instructions how. The QuartzJobBean is passed the current JobExecutionContext when it runs.

like image 45
skaffman Avatar answered Dec 13 '22 22:12

skaffman