<bean id="itemReader" class="org.springframework.batch.item.adapter.ItemReaderAdapter">
<property name="targetObject" ref="fooService" />
<property name="targetMethod" value="generateFoo" />
</bean>
鉴于这个简单的设置,fooService是一个简单的pojo spring bean。
如果fooService实现了ItemStream并且我实现了openclin和open方法,那么我的ItemReader是否可以重启?
此致
答案 0 :(得分:4)
好的,我终于回答了我自己的问题。
我发现ItemReaderAdapter非常有用,因为大多数时候我们已经有某种DAO或服务可以访问我们需要的数据。
但我的测试告诉我,如果我使用ItemReaderAdapter impl。开箱即用,它们不能重新启动,因为它们没有实现ItemStream!
因此,如果你们中任何人想要使用具有可重启功能的ItemReaderAdapter,那么这就是我的解决方案。
经过测试和工作; - )
1)创建自己的ItemReaderAdapter实现:
package xxx.readers.adapters;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.adapter.AbstractMethodInvokingDelegator;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Invokes a custom method on a delegate plain old Java object which itself
* provides an item.
*
* overriden to implements the ItemStream interface
*
* @author Benoit Campeau
*/
public class MyItemReaderAdapter<T> extends AbstractMethodInvokingDelegator<T> implements ItemReader<T>, ItemStream {
private static final Logger log = Logger.getLogger(MyItemReaderAdapter.class);
private long currentCount = 0;
private final String CONTEXT_COUNT_KEY = "ReglementAdapter.count";
/**
* @return return value of the target method.
*/
public T read() throws Exception {
super.setArguments(new Long[]{currentCount++});
return invokeDelegateMethod();
}
@Override
public void open(ExecutionContext executionContext)
throws ItemStreamException {
currentCount = executionContext.getLong(CONTEXT_COUNT_KEY,0);
log.info("Open Stream current count : " + currentCount);
}
@Override
public void update(ExecutionContext executionContext) throws ItemStreamException {
executionContext.putLong(CONTEXT_COUNT_KEY, currentCount);
log.info("Update Stream current count : " + currentCount);
}
@Override
public void close() throws ItemStreamException {
// TODO Auto-generated method stub
}
}
2)现在使用你的impl将Reader配置为适配器。 (MyItemReaderAdapter)。强>
<bean id="MyReader" class="xxx.readers.adapters.MyItemReaderAdapter">
<property name="targetObject" ref="someAdapter" />
<property name="targetMethod" value="next" />
</bean>
3)最后,创建一个将作为Adapter委托类的Component:
package fcdq.iemt.batch.validation.reglement.readers.adapters;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("someAdapter")
public class SomeAdapter {
private static final Logger log = Logger.getLogger(SomeAdapter .class);
@Autowired
private SomeService srv1;
private List<Transaction> listTrx;
public void init() {
log.info("Initializing " + SomeAdapter.class.toString() );
listTrx = srv1.findByTimestampAndStatus(context.getBeginTSCutoff(), context.getEndTSCutoff(), TransactionTypeEnum.TRANSFER_COMPLETE);
}
/**
* read method delegate
* @return
*/
public Transaction next(Long index) {
if (listTrx != null && listTrx.size() > index ) {
return listTrx.get(index.intValue());
} else {
return null;
}
}
}
注意事项:
注意MyItemReaderAdapter中的setArguments。这必须将execution_context中存储的currentCount的值传递给委托read()方法
请注意,MyItemReaderAdapter不实现InitializingBean接口。我使用stepListener代替,因为我想初始化我要及时阅读的项目列表。
希望它会帮助别人。
此致
答案 1 :(得分:0)
实现相同目标的另一种方法是扩展AbstractItemCountingItemStreamItemReader
来自文档::
ItemReaders的抽象超类,支持通过存储重新启动 ExecutionContext中的项目计数(因此需要项目排序 在运行之间保留)。子类本质上不是 线程安全
示例代码:
package com.***.batch.reader;
import java.util.List;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.mivim.campaignmanager.data.model.custom.CustomCampaignSubscriberEmail;
import com.mivim.campaignmanager.service.CampaignSubscriberService;
@Component
public class CampaignSubscriberItemReader extends
AbstractItemCountingItemStreamItemReader<CustomCampaignSubscriberEmail> {
private Logger logger = LogManager.getLogger(CampaignSubscriberItemReader.class);
@Autowired
CampaignSubscriberService campaignSubscriberService;
List<CustomCampaignSubscriberEmail> customCampaignSubscriberEmails;
final String ecName = "csItemReaderContext";
public CampaignSubscriberItemReader() {
setName(ecName);
}
@Override
protected CustomCampaignSubscriberEmail doRead() throws Exception {
CustomCampaignSubscriberEmail customCampaignSubscriberEmail = customCampaignSubscriberEmails
.get(getCurrentItemCount() - 1);
return customCampaignSubscriberEmail;
}
@Override
protected void doOpen() throws Exception {
customCampaignSubscriberEmails = campaignSubscriberService.getPendingCampaignSubscriber();
setMaxItemCount(customCampaignSubscriberEmails.size());
}
@Override
protected void doClose() throws Exception {
customCampaignSubscriberEmails.clear();
setMaxItemCount(0);
setCurrentItemCount(0);
}
}