Skip to content

Commit

Permalink
SPR-14471 - Add autowiring support to SpringBeanJobFactory
Browse files Browse the repository at this point in the history
This commit introduces autowiring support to the SpringBeanJobFactory.
It will call the autowireBean method if an AutowireCapableBeanFactory
has been injected.

A test has been added to verify the correct behavior of the autowiring
and as well as retaining the initial support of using the job data for
wiring dependencies.
  • Loading branch information
mdeinum committed Oct 4, 2018
1 parent 3ff5731 commit 007a339
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 4 deletions.
Expand Up @@ -18,10 +18,13 @@

import org.quartz.SchedulerContext;
import org.quartz.spi.TriggerFiredBundle;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.Nullable;

/**
Expand All @@ -37,17 +40,19 @@
* <p>Compatible with Quartz 2.1.4 and higher, as of Spring 4.1.
*
* @author Juergen Hoeller
* @author Marten Deinum
* @since 2.0
* @see SchedulerFactoryBean#setJobFactory
* @see QuartzJobBean
*/
public class SpringBeanJobFactory extends AdaptableJobFactory implements SchedulerContextAware {
public class SpringBeanJobFactory extends AdaptableJobFactory implements SchedulerContextAware, ApplicationContextAware {

@Nullable
private String[] ignoredUnknownProperties;

@Nullable
private SchedulerContext schedulerContext;
private AutowireCapableBeanFactory beanFactory;


/**
Expand All @@ -67,7 +72,6 @@ public void setSchedulerContext(SchedulerContext schedulerContext) {
this.schedulerContext = schedulerContext;
}


/**
* Create the job instance, populating it with property values taken
* from the scheduler context, job data map and trigger data map.
Expand Down Expand Up @@ -95,7 +99,8 @@ protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
bw.setPropertyValues(pvs, true);
}
}
return job;
this.beanFactory.autowireBean(job);
return this.beanFactory.initializeBean(job, "");
}

/**
Expand All @@ -110,4 +115,9 @@ protected boolean isEligibleForPropertyPopulation(Object jobObject) {
return (!(jobObject instanceof QuartzJobBean));
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.beanFactory=applicationContext.getAutowireCapableBeanFactory();
}

}
@@ -0,0 +1,80 @@
package org.springframework.scheduling.quartz;

import java.util.Date;

import org.junit.Test;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.sameInstance;

/**
* Tests for the {@link SpringBeanJobFactory}
*
* @author Marten Deinum
*/
public class SpringBeanJobFactoryTest {

@Test
public void shouldSetParameterFromContextAndAutowireDependenciesInAJob() throws Exception {
ApplicationContext context = loadContext();
TriggerFiredBundle tfb = createTrigger(context, "jobDetailWithJob");

SpringBeanJobFactory factory = context.getBean(SpringBeanJobFactory.class);

DummyJob job = (DummyJob) factory.createJobInstance(tfb);

assertThat(job.getDummyBean(), sameInstance(context.getBean(DummyBean.class)));
assertThat(job.getParam(), is(42));
}

private ApplicationContext loadContext() {
return new ClassPathXmlApplicationContext("scheduler-with-job-factory.xml", SpringBeanJobFactoryTest.class);
}


private TriggerFiredBundle createTrigger(ApplicationContext context, String name) {
final Date now = new Date();
final JobDetail jobDetail = context.getBean(name, JobDetail.class);
return new TriggerFiredBundle(jobDetail, new SimpleTriggerImpl(), null, false, now, now, now, now);
}


public static class DummyBean {
}

public static class DummyJob implements Job {

private int param;

@Autowired
private DummyBean dummyBean;


@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
}


public void setParam(int value) {
param = value;
}

public int getParam() {
return param;
}

public DummyBean getDummyBean() {
return dummyBean;
}
}
}
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<context:annotation-config />

<bean id="jobDetailWithJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="org.springframework.scheduling.quartz.SpringBeanJobFactoryTest$DummyJob" />
<property name="jobDataAsMap">
<map>
<entry key="param" value="42" />
</map>
</property>
</bean>

<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactoryTest$DummyBean" />

<bean id="jobFactory" class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />

</beans>

0 comments on commit 007a339

Please sign in to comment.