Reputation: 2535
I have some troubles with a very basic scenario: I have a java web app (spring 3) and I want to store some object to a stack. Then I want to manage the objects in the stack with a scheduler and so I implemented a quartz job. Plain and simple. I inject the stack in the first service class and in the job class with @Autowired annotation. For the service class the table is succesfully injected but for the job class the table is null. here's the code:
the class to share
package it.unifi.det.telemat.vr.data;
@Component
public class IndexedNodesStack extends HashMap<IndexedObject, Boolean>{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public synchronized int size() {
// TODO Auto-generated method stub
return super.size();
}
//all the HashMap methods are implemented in a synchronized wrapper method
}
the first class (@Autowired is successful)
package it.unifi.det.telemat.vr.service;
@Service
public class InnerNodeManager extends ConcreteNodeManager{
@Autowired
private IndexedNodesStack indexedNodesStack; //<--- it is actually autowired!
private void manageIndexedNodes(Boolean isPut, String lri, String features)
{
IndexedObject indexedObject = new IndexedObject();
indexedObject.setId(lri);
if(features != null && isPut)
indexedObject.generateFeatures(features);
indexedNodesStack.put(indexedObject, isPut);
}
}
the job class (@Autowired fails)
package it.unifi.det.telemat.vr.service.scheduler;
@Component
public class QuartzJSearchJob extends QuartzJobBean{
@Autowired
private IndexedNodesStack indexedNodesStack; //<--- this variable is null :-(
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException
{
//do work
}
}
EDIT: here's the servlet.xml
<context:component-scan base-package="it.unifi.det.telemat.vr" />
<bean name="searchJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="it.unifi.det.telemat.vr.service.scheduler.QuartzJSearchJob" />
</bean>
<bean id="searchJobTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="searchJob" />
<property name="cronExpression" value="0/50 * * * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="searchJobTrigger" />
</list>
</property>
</bean>
maybe I lack some knowledge about the resource sharing between threads since it is my first attempt in this field. What am I missing?
Upvotes: 2
Views: 3238
Reputation: 1
I have same problem, I resolved this by adding SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
as first line of my Job.execute(JobExecutionContext context)
method.
Upvotes: 0
Reputation: 531
You forget the "jobDetails" property :
<property name="jobDetails">
<list>
<ref bean="searchJob" />
</list>
</property>
You also need to use org.springframework.scheduling.quartz.JobDetailFactoryBean
instead of org.springframework.scheduling.quartz.JobDetailBean
.
Insert it like this :
<bean name="searchJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="it.unifi.det.telemat.vr.service.scheduler.QuartzJSearchJob" />
</bean>
<bean id="searchJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="searchJob" />
<property name="cronExpression" value="0/50 * * * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="searchJobTrigger" />
</list>
</property>
<property name="jobDetails">
<list>
<ref bean="searchJob" />
</list>
</property>
</bean>
Upvotes: 0
Reputation: 95
I think you must assign a value in scheduleFactoryBean
, setSchedulerContextAsMap()
, you put your object in this map, then it will work.
@Bean(name = "scheduler")
public SchedulerFactoryBean schedulerFactory()
{
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setDataSource(dataSource);
schedulerFactory.setAutoStartup(true);
schedulerFactory.setGlobalJobListeners(globalJobListeners);
schedulerFactory.setSchedulerContextAsMap(contextMap());
schedulerFactory.setQuartzProperties(schedulerProperties());
return schedulerFactory;
}
Upvotes: -2
Reputation: 2535
ok, finally I get the point.
It doesn't works becaouse spring does not instantiate the quartzJSearchJob, quartz does. The beans to inject inside the job have to be passed via SchedulerFacoryBean
.
Here's the configuration that makes the things work.
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="searchJobTrigger" />
</list>
</property>
<property name="schedulerContextAsMap">
<map>
<entry key="indexedNodesStack" value-ref="indexedNodesStack" />
</map>
</property>
</bean>
Upvotes: 2
Reputation: 8969
Autowiring only works if the bean is created from Spring bean factory. Did you create the object without using bean factory, i.e. create it using new QuartzJSearchJob()
syntax?
Upvotes: 2
Reputation: 4218
QuartzJSearchJob
isn't recognized as a bean, because it doesn't have a class level annotation. Try @Component
Upvotes: 0