我们正在使用Spring Batch Chunk从JMS目标读取消息并写入平面文件。在这方面,我们有以下观察,
如果消息代理在读取器读取消息并且未达到提交计数时关闭,则到目前为止读取的消息数将被传递给Writer,然后批处理将进入FAILED状态。这是Chunk的默认行为吗?
如果第1点的答案为YES,我们如何确保不将此部分块发送给Writer。 (为了给出这个问题的更多背景知识,我们在JMS模板中进行了JMS会话处理,因此当块无法读取等于提交计数的完整数量的消息时,部分块中读取的所有消息都将回滚到JMS目标,即将相同的部分块写入文件。当我们重新启动批处理作业时,这会导致文件中出现重复。)
非常感谢任何帮助。
修改
配置如下所示,
组块:
<batch:step id="step-1" next="step-2">
<batch:tasklet allow-start-if-complete="false">
<batch:chunk reader="jms-reader-1-1" writer="file-writer-1-1" commit-interval="1000">
</batch:chunk>
</batch:step>
作家(平面文件):
<bean scope="step" class="o.s.b.i.f.FlatFileItemWriter" id="file-writer-1-1">
<property name="resource" value="file:#{T(com.test.core.BatchConfiguration).BATCH_VFS_LOCAL_TEMP_LOCATION}/#{T(com.test.utils.ThreadContextUtils).getJobInstanceIdAsString()}/AssetMesage"/>
<property name="lineAggregator">
<bean class="o.s.b.i.f.t.DelimitedLineAggregator">
<property name="delimiter" value=","/>
<property name="fieldExtractor">
<bean class="o.s.b.i.f.t.BeanWrapperFieldExtractor">
<property name="names" value="assetId,assetName,assetDesc"/>
</bean>
</property>
</bean>
</property>
</bean>
读者(JMS):
<bean scope="step" class="com.test.runtime.impl.item.readers.JMSItemReader" id="jms-reader-1-1">
<property name="adapter">
<bean class="com.test.adapter.impl.JMSAdapter">
<property name="resource" ref="JMS.vmsmartbatch02_Regression"/>
<property name="retryerId" value="JMS.vmsmartbatch02_Regression-retryer"/>
</bean>
</property>
<property name="destination" value="#{jobParameters[source1jmsdestination] != null ? jobParameters[source1jmsdestination] : "sourceTopic"}"/><property name="durableSubscriberName" value="sourceTopicDS"/><property name="destinationType" value="Topic"/>
<property name="ackMode" value="#{T(javax.jms.Session).CLIENT_ACKNOWLEDGE}"/>
<property name="maxMessageCount" value="2000"/>
</bean>
编辑2
下面是我正在使用的核心阅读器逻辑,
阅读器
public Object read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
Object item = null;
try {
if(ackMode != 0 && ackMode >= 1 && ackMode <= 3){
adapter.getResource().setSessionAcknowledgeMode(ackMode);
}
if(maxMessageCount > 0){
ThreadContextUtils.addToExecutionContext("maxMessageCount", maxMessageCount);
if(ThreadContextUtils.getExecutionContext().containsKey("readMessageCount")) {
readMessageCount = ThreadContextUtils.getExecutionContext().getInt("readMessageCount");
}
}
if (TOPIC_KEY.equalsIgnoreCase(destinationType)
&& durableSubscriberName != null) {
item = (Object) adapter.invoke(REC_DS_AND_CONVERT_SELECTED,
OBJECT_CLASS, destination, durableSubscriberName,
receiveTimeout, filter == null ? "" : filter);
} else {
item = (Object) adapter.invoke(REC_AND_CONVERT_SELECTED,
OBJECT_CLASS, destination,
receiveTimeout <= 0 ? adapter.getResource()
.getReceiveTimeout() : receiveTimeout,
(filter == null ? "" : filter));
}
if(maxMessageCount > 0){
if( item !=null){
readMessageCount++;
ThreadContextUtils.addToExecutionContext("readMessageCount", readMessageCount);
}
}
return item;
} finally {
}
}