MaVVamaldo MaVVamaldo - 14 days ago 8
Java Question

@Autowired doesn't work if applied to a bean shared between two threads

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?

Answer

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>