は、私は私の春バッチItemReaderにサービスやDAO Beanを注入しようとしている1つの更新を注入豆
については、以下を参照してください。しかし、注入された参照はNULLです。 XMLファイルで@Autowireと明示的なBean設定を使って試しました。
ジョブは、spring-mvcアプリケーションから実行されています。このItemReaderは、処理するIDのリストをロードするためにDBアクセスを必要とします。このリストを通してリーダが読み込み、ItemWriterは、既存のサービスとDAOレイヤを使用して各IDのデータベースに対して必要な変更を行います。ここで
は、このバージョンでは、私が注入しようとしている、また、私の構成(それが別々のスプリングbatch.xmlファイルに定義されているアプリケーションコンテキストXMLファイルの後のweb.xmlに含まれています。)
ですXML構成を使用してItemReaderにJobService Beanを追加します。
ここでの一般的な問題は、他のDAOやサービスをアイテムリーダやライターに挿入する方法ですか?
<beans:bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<beans:property name="dataSource" ref="dataSourceJNDI" />
<beans:property name="transactionManager" ref="transactionManager" />
<beans:property name="databaseType" value="mysql" />
</beans:bean>
<beans:bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<beans:property name="jobRepository" ref="jobRepository" />
</beans:bean>
<beans:bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
<beans:bean id="myItemReader" class="my.MyItemReader" scope="step">
<beans:property name="jobService">
<beans:bean class="my.JobService"></beans:bean>
</beans:property>
</beans:bean>
<job id="assignLeadBatch" restartable="false" job-repository="jobRepository">
<step id="step1">
<tasklet transaction-manager="dbOpsTransactionManager">
<chunk reader="myItemReader" writer="myItemWriter" commit-interval="10" />
</tasklet>
</step>
</job>
<beans:bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<beans:property name="jobRegistry" ref="jobRegistry" />
</beans:bean>
ItemReader:
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
@Component
public class MyItemReader implements ItemReader<Integer> {
JobService jobService;
private List<Integer> itemsList;
@Autowired
public AssignLeadsJobItemReader(@Value("#{jobParameters['jobKey']}") final String jobKey) {
MyJob alj = jobService.loadByKey(jobKey);
itemsList = new ArrayList<AssignLeadsJobItem>();
for(Integer i : myJob.getIdList()) {
itemsList.add(i);
}
}
@Override
public Integer read(){
if(itemsList == null || itemsList.size() == 0) {
return null;
} else {
return itemsList.remove(0);
}
}
public JobService getJobService() {
return jobService;
}
public void setJobService(JobService jobService) {
this.jobService = jobService;
}
}
ジョブサービス:
@Service
@Transactional
public class JobService {
@Autowired
protected JobDAO jobDao;
@Autowired
protected SpringBatchService springBatchService;
public JobExecution startJob(String jobName, String jobKey) {
// Defined in a different Class without transactions.
return springBatchService.startJob("job_name", jobKey);
}
public MyJob loadByKey(String jobKey) {
return jobDao.loadByKey(jobKey);
}
}
UPDATE 1 このエラーは、ItemReaderコンストラクタの参照を呼び出すことによって発生していることに気付きました。私はこのコードを次のように変更しました:
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
@Component
public class MyItemReader implements ItemReader<Integer> {
private JobService jobService;
private List<Integer> itemsList;
private String jobKey;
@Autowired
public MyItemReader(@Value("#{jobParameters['jobKey']}") final String jobKey) {
this.jobKey = jobKey;
this.itemsList = null;
}
@Override
public Integer read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
// ugly ugly ugly
if (itemsList == null) {
itemsList = new ArrayList<Integer>();
MyJob jobData = jobService.loadByKey(jobKey);
for (Integer i : jobData.getIdList()) {
itemsList.add(i);
}
}
if (itemsList.isEmpty()) {
return null;
} else {
return itemsList.remove(0);
}
}
}
コンストラクタでその醜い初期化を行う方法はありますか?
job.serviceをシングルトンとして宣言し、property-ref –
Thanks @ Lucaを使用してリーダーに配線します。私はyorの提案に従ってコードを変更しました。私はさらに、ItemReaderのコンストラクタでDAOを呼び出していることに問題があることに気付きました。 read()メソッドでarrayList(DAOから)を初期化するように変更しました。最初にList == nullかどうかをチェックし、そうであればそれを初期化し、次に要素を返します。しかし、この初期化はコンストラクタ上になければならないため、これは扱いにくいようです。そこからそれを動作させる方法はありますか?また、私はそれを受け入れることができるように、あなたのコメントの回答をしてください! – tggm