2012-05-03 4 views
2

У меня есть некоторые проблемы с очень простым сценарием: у меня есть веб-приложение java (весна 3), и я хочу сохранить некоторый объект в стек. Затем я хочу управлять объектами в стеке с помощью планировщика, и поэтому я выполнил кварцевое задание. Легко и просто. Я вставляю стек в первый класс сервиса и в класс задания с @Autowired аннотацией. Для класса сервиса таблица успешно вводится, но для класса задания таблица равна нулю. вот код:@Autowired не работает, если применяется к компоненту, разделяемому между двумя потоками

класс поделиться

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 

} 

первый класс (@Autowired успешна)

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); 
    } 

} 

класс работы (@Autowired сбой)

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: вот сервлет.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> 

Возможно, мне не хватает знаний об обмене ресурсами между потоками, так как это моя первая попытка в этой области. Что мне не хватает?

+0

вам нужно будет показать, как вы создаете объект, чтобы объяснить, почему он не будет правильно инициализирован весной. как он инициализируется? – ianpojman

+0

задание создается с помощью аннотации @Component (я отредактировал мой вопрос, чтобы исправить его) – MaVVamaldo

ответ

2

ОК, наконец, я понял. Это не работает becaouse spring не создает экземпляр quartzJSearchJob, кварц делает. Бобы для инъекций внутри задания должны быть переданы через SchedulerFacoryBean. Вот конфигурация, которая заставляет вещи работать.

<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> 
0

QuartzJSearchJob не признан в качестве компонента, поскольку он не имеет аннотации уровня класса. Попробуйте @Component

+0

моя ошибка, я опустил @Component в операции вставки, пока он действительно присутствовал в коде. Я редактировал свой вопрос. – MaVVamaldo

2

Autowiring работает только в том случае, если фасоль создана на фабрике весна-фасоль. Вы создали объект без использования фабрики bean, т. Е. Создали его с помощью синтаксиса new QuartzJSearchJob()?

+0

Я пытаюсь создать его с помощью аннотации @Component – MaVVamaldo

+0

Можете ли вы опубликовать конфигурацию своего компонента? Добавление @Component не помогает, если bean-компонент не создается фабрикой bean. – gigadot

+0

да, только что сделано :-) – MaVVamaldo

-2

Я думаю, вы должны присвоить значение в scheduleFactoryBean, setSchedulerContextAsMap(), вы кладете свой объект на этой карте, то он будет работать.

@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; 
    } 
0

Вы забыли свойство "jobDetails":

<property name="jobDetails"> 
    <list> 
     <ref bean="searchJob" /> 
    </list> 
</property> 

Вы также должны использовать org.springframework.scheduling.quartz.JobDetailFactoryBean вместо org.springframework.scheduling.quartz.JobDetailBean.

Вставьте это так:

<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> 
0

Я такая же проблема, я решил, добавив SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); в первой строке моего Job.execute(JobExecutionContext context) метода.