Use lambdas and method references where appropriate
This commit is contained in:
@@ -17,7 +17,6 @@ package org.springframework.batch.core.job.flow.support.state;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
@@ -89,12 +88,7 @@ public class SplitState extends AbstractState implements FlowHolder {
|
||||
|
||||
for (final Flow flow : flows) {
|
||||
|
||||
final FutureTask<FlowExecution> task = new FutureTask<>(new Callable<>() {
|
||||
@Override
|
||||
public FlowExecution call() throws Exception {
|
||||
return flow.start(executor);
|
||||
}
|
||||
});
|
||||
final FutureTask<FlowExecution> task = new FutureTask<>(() -> flow.start(executor));
|
||||
|
||||
tasks.add(task);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.batch.core.partition.support;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
@@ -129,12 +128,9 @@ public class TaskExecutorPartitionHandler extends AbstractPartitionHandler imple
|
||||
* @return the task executing the given step
|
||||
*/
|
||||
protected FutureTask<StepExecution> createTask(final Step step, final StepExecution stepExecution) {
|
||||
return new FutureTask<>(new Callable<>() {
|
||||
@Override
|
||||
public StepExecution call() throws Exception {
|
||||
step.execute(stepExecution);
|
||||
return stepExecution;
|
||||
}
|
||||
return new FutureTask<>(() -> {
|
||||
step.execute(stepExecution);
|
||||
return stepExecution;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import org.springframework.batch.core.repository.ExecutionContextSerializer;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.core.serializer.Serializer;
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.PreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.lob.DefaultLobHandler;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
@@ -289,18 +288,15 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem
|
||||
longContext = null;
|
||||
}
|
||||
|
||||
getJdbcTemplate().update(getQuery(sql), new PreparedStatementSetter() {
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps) throws SQLException {
|
||||
ps.setString(1, shortContext);
|
||||
if (longContext != null) {
|
||||
lobHandler.getLobCreator().setClobAsString(ps, 2, longContext);
|
||||
}
|
||||
else {
|
||||
ps.setNull(2, getClobTypeToUse());
|
||||
}
|
||||
ps.setLong(3, executionId);
|
||||
getJdbcTemplate().update(getQuery(sql), ps -> {
|
||||
ps.setString(1, shortContext);
|
||||
if (longContext != null) {
|
||||
lobHandler.getLobCreator().setClobAsString(ps, 2, longContext);
|
||||
}
|
||||
else {
|
||||
ps.setNull(2, getClobTypeToUse());
|
||||
}
|
||||
ps.setLong(3, executionId);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -373,12 +373,9 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
public Set<JobExecution> findRunningJobExecutions(String jobName) {
|
||||
|
||||
final Set<JobExecution> result = new HashSet<>();
|
||||
RowCallbackHandler handler = new RowCallbackHandler() {
|
||||
@Override
|
||||
public void processRow(ResultSet rs) throws SQLException {
|
||||
JobExecutionRowMapper mapper = new JobExecutionRowMapper();
|
||||
result.add(mapper.mapRow(rs, 0));
|
||||
}
|
||||
RowCallbackHandler handler = rs -> {
|
||||
JobExecutionRowMapper mapper = new JobExecutionRowMapper();
|
||||
result.add(mapper.mapRow(rs, 0));
|
||||
};
|
||||
getJdbcTemplate().query(getQuery(GET_RUNNING_EXECUTIONS), handler, jobName);
|
||||
|
||||
@@ -455,27 +452,24 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
*/
|
||||
protected JobParameters getJobParameters(Long executionId) {
|
||||
final Map<String, JobParameter<?>> map = new HashMap<>();
|
||||
RowCallbackHandler handler = new RowCallbackHandler() {
|
||||
@Override
|
||||
public void processRow(ResultSet rs) throws SQLException {
|
||||
String parameterName = rs.getString("PARAMETER_NAME");
|
||||
RowCallbackHandler handler = rs -> {
|
||||
String parameterName = rs.getString("PARAMETER_NAME");
|
||||
|
||||
Class<?> parameterType = null;
|
||||
try {
|
||||
parameterType = Class.forName(rs.getString("PARAMETER_TYPE"));
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String stringValue = rs.getString("PARAMETER_VALUE");
|
||||
Object typedValue = conversionService.convert(stringValue, parameterType);
|
||||
|
||||
boolean identifying = rs.getString("IDENTIFYING").equalsIgnoreCase("Y");
|
||||
|
||||
JobParameter<?> jobParameter = new JobParameter(typedValue, parameterType, identifying);
|
||||
|
||||
map.put(parameterName, jobParameter);
|
||||
Class<?> parameterType = null;
|
||||
try {
|
||||
parameterType = Class.forName(rs.getString("PARAMETER_TYPE"));
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String stringValue = rs.getString("PARAMETER_VALUE");
|
||||
Object typedValue = conversionService.convert(stringValue, parameterType);
|
||||
|
||||
boolean identifying = rs.getString("IDENTIFYING").equalsIgnoreCase("Y");
|
||||
|
||||
JobParameter<?> jobParameter = new JobParameter(typedValue, parameterType, identifying);
|
||||
|
||||
map.put(parameterName, jobParameter);
|
||||
};
|
||||
|
||||
getJdbcTemplate().query(getQuery(FIND_PARAMS_FROM_ID), handler, executionId);
|
||||
|
||||
@@ -221,12 +221,7 @@ public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements
|
||||
*/
|
||||
@Override
|
||||
public List<String> getJobNames() {
|
||||
return getJdbcTemplate().query(getQuery(FIND_JOB_NAMES), new RowMapper<>() {
|
||||
@Override
|
||||
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return rs.getString(1);
|
||||
}
|
||||
});
|
||||
return getJdbcTemplate().query(getQuery(FIND_JOB_NAMES), (rs, rowNum) -> rs.getString(1));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2022 the original author or authors.
|
||||
* Copyright 2006-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.batch.core.repository.support;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.aop.support.NameMatchMethodPointcut;
|
||||
@@ -197,15 +196,12 @@ public abstract class AbstractJobRepositoryFactoryBean implements FactoryBean<Jo
|
||||
TransactionInterceptor advice = new TransactionInterceptor((TransactionManager) this.transactionManager,
|
||||
this.transactionAttributeSource);
|
||||
if (this.validateTransactionState) {
|
||||
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(new MethodInterceptor() {
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
if (TransactionSynchronizationManager.isActualTransactionActive()) {
|
||||
throw new IllegalStateException("Existing transaction detected in JobRepository. "
|
||||
+ "Please fix this and try again (e.g. remove @Transactional annotations from client).");
|
||||
}
|
||||
return invocation.proceed();
|
||||
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor((MethodInterceptor) invocation -> {
|
||||
if (TransactionSynchronizationManager.isActualTransactionActive()) {
|
||||
throw new IllegalStateException("Existing transaction detected in JobRepository. "
|
||||
+ "Please fix this and try again (e.g. remove @Transactional annotations from client).");
|
||||
}
|
||||
return invocation.proceed();
|
||||
});
|
||||
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
|
||||
pointcut.addMethodName("create*");
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* ScopeSupport.
|
||||
@@ -174,12 +173,7 @@ public abstract class BatchScopeSupport implements Scope, BeanFactoryPostProcess
|
||||
private final boolean scoped;
|
||||
|
||||
public Scopifier(BeanDefinitionRegistry registry, String scope, boolean proxyTargetClass, boolean scoped) {
|
||||
super(new StringValueResolver() {
|
||||
@Override
|
||||
public String resolveStringValue(String value) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
super(value -> value);
|
||||
this.registry = registry;
|
||||
this.proxyTargetClass = proxyTargetClass;
|
||||
this.scope = scope;
|
||||
|
||||
@@ -215,87 +215,77 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
|
||||
|
||||
final I item = iterator.next();
|
||||
|
||||
RetryCallback<O, Exception> retryCallback = new RetryCallback<>() {
|
||||
|
||||
@Override
|
||||
public O doWithRetry(RetryContext context) throws Exception {
|
||||
Timer.Sample sample = BatchMetrics.createTimerSample(meterRegistry);
|
||||
String status = BatchMetrics.STATUS_SUCCESS;
|
||||
O output = null;
|
||||
try {
|
||||
O cached = (cacheIterator != null && cacheIterator.hasNext()) ? cacheIterator.next() : null;
|
||||
if (cached != null && !processorTransactional) {
|
||||
output = cached;
|
||||
}
|
||||
else {
|
||||
output = doProcess(item);
|
||||
if (output == null) {
|
||||
data.incrementFilterCount();
|
||||
}
|
||||
else if (!processorTransactional && !data.scanning()) {
|
||||
cache.add(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
status = BatchMetrics.STATUS_FAILURE;
|
||||
if (rollbackClassifier.classify(e)) {
|
||||
// Default is to rollback unless the classifier
|
||||
// allows us to continue
|
||||
throw e;
|
||||
}
|
||||
else if (shouldSkip(itemProcessSkipPolicy, e, contribution.getStepSkipCount())) {
|
||||
// If we are not re-throwing then we should check if
|
||||
// this is skippable
|
||||
contribution.incrementProcessSkipCount();
|
||||
logger.debug("Skipping after failed process with no rollback", e);
|
||||
// If not re-throwing then the listener will not be
|
||||
// called in next chunk.
|
||||
callProcessSkipListener(item, e);
|
||||
}
|
||||
else {
|
||||
// If it's not skippable that's an error in
|
||||
// configuration - it doesn't make sense to not roll
|
||||
// back if we are also not allowed to skip
|
||||
throw new NonSkippableProcessException(
|
||||
"Non-skippable exception in processor. Make sure any exceptions that do not cause a rollback are skippable.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stopTimer(sample, contribution.getStepExecution(), "item.process", status, "Item processing");
|
||||
}
|
||||
if (output == null) {
|
||||
// No need to re-process filtered items
|
||||
iterator.remove();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
RecoveryCallback<O> recoveryCallback = new RecoveryCallback<>() {
|
||||
|
||||
@Override
|
||||
public O recover(RetryContext context) throws Exception {
|
||||
Throwable e = context.getLastThrowable();
|
||||
if (shouldSkip(itemProcessSkipPolicy, e, contribution.getStepSkipCount())) {
|
||||
iterator.remove(e);
|
||||
contribution.incrementProcessSkipCount();
|
||||
logger.debug("Skipping after failed process", e);
|
||||
return null;
|
||||
RetryCallback<O, Exception> retryCallback = context -> {
|
||||
Timer.Sample sample = BatchMetrics.createTimerSample(meterRegistry);
|
||||
String status = BatchMetrics.STATUS_SUCCESS;
|
||||
O output = null;
|
||||
try {
|
||||
O cached = (cacheIterator != null && cacheIterator.hasNext()) ? cacheIterator.next() : null;
|
||||
if (cached != null && !processorTransactional) {
|
||||
output = cached;
|
||||
}
|
||||
else {
|
||||
if (rollbackClassifier.classify(e)) {
|
||||
// Default is to rollback unless the classifier
|
||||
// allows us to continue
|
||||
throw new RetryException("Non-skippable exception in recoverer while processing", e);
|
||||
output = doProcess(item);
|
||||
if (output == null) {
|
||||
data.incrementFilterCount();
|
||||
}
|
||||
else if (!processorTransactional && !data.scanning()) {
|
||||
cache.add(output);
|
||||
}
|
||||
iterator.remove(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
status = BatchMetrics.STATUS_FAILURE;
|
||||
if (rollbackClassifier.classify(e)) {
|
||||
// Default is to rollback unless the classifier
|
||||
// allows us to continue
|
||||
throw e;
|
||||
}
|
||||
else if (shouldSkip(itemProcessSkipPolicy, e, contribution.getStepSkipCount())) {
|
||||
// If we are not re-throwing then we should check if
|
||||
// this is skippable
|
||||
contribution.incrementProcessSkipCount();
|
||||
logger.debug("Skipping after failed process with no rollback", e);
|
||||
// If not re-throwing then the listener will not be
|
||||
// called in next chunk.
|
||||
callProcessSkipListener(item, e);
|
||||
}
|
||||
else {
|
||||
// If it's not skippable that's an error in
|
||||
// configuration - it doesn't make sense to not roll
|
||||
// back if we are also not allowed to skip
|
||||
throw new NonSkippableProcessException(
|
||||
"Non-skippable exception in processor. Make sure any exceptions that do not cause a rollback are skippable.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stopTimer(sample, contribution.getStepExecution(), "item.process", status, "Item processing");
|
||||
}
|
||||
if (output == null) {
|
||||
// No need to re-process filtered items
|
||||
iterator.remove();
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
RecoveryCallback<O> recoveryCallback = context -> {
|
||||
Throwable e = context.getLastThrowable();
|
||||
if (shouldSkip(itemProcessSkipPolicy, e, contribution.getStepSkipCount())) {
|
||||
iterator.remove(e);
|
||||
contribution.incrementProcessSkipCount();
|
||||
logger.debug("Skipping after failed process", e);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
if (rollbackClassifier.classify(e)) {
|
||||
// Default is to rollback unless the classifier
|
||||
// allows us to continue
|
||||
throw new RetryException("Non-skippable exception in recoverer while processing", e);
|
||||
}
|
||||
iterator.remove(e);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
O output = batchRetryTemplate.execute(retryCallback, recoveryCallback,
|
||||
@@ -328,76 +318,68 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
|
||||
final UserData<O> data = (UserData<O>) inputs.getUserData();
|
||||
final AtomicReference<RetryContext> contextHolder = new AtomicReference<>();
|
||||
|
||||
RetryCallback<Object, Exception> retryCallback = new RetryCallback<>() {
|
||||
@Override
|
||||
public Object doWithRetry(RetryContext context) throws Exception {
|
||||
contextHolder.set(context);
|
||||
RetryCallback<Object, Exception> retryCallback = context -> {
|
||||
contextHolder.set(context);
|
||||
|
||||
if (!data.scanning()) {
|
||||
chunkMonitor.setChunkSize(inputs.size());
|
||||
Timer.Sample sample = BatchMetrics.createTimerSample(meterRegistry);
|
||||
String status = BatchMetrics.STATUS_SUCCESS;
|
||||
try {
|
||||
doWrite(outputs);
|
||||
}
|
||||
catch (Exception e) {
|
||||
status = BatchMetrics.STATUS_FAILURE;
|
||||
if (rollbackClassifier.classify(e)) {
|
||||
throw e;
|
||||
}
|
||||
/*
|
||||
* If the exception is marked as no-rollback, we need to override
|
||||
* that, otherwise there's no way to write the rest of the chunk
|
||||
* or to honour the skip listener contract.
|
||||
*/
|
||||
throw new ForceRollbackForWriteSkipException(
|
||||
"Force rollback on skippable exception so that skipped item can be located.", e);
|
||||
}
|
||||
finally {
|
||||
stopTimer(sample, contribution.getStepExecution(), "chunk.write", status, "Chunk writing");
|
||||
}
|
||||
contribution.incrementWriteCount(outputs.size());
|
||||
if (!data.scanning()) {
|
||||
chunkMonitor.setChunkSize(inputs.size());
|
||||
Timer.Sample sample = BatchMetrics.createTimerSample(meterRegistry);
|
||||
String status = BatchMetrics.STATUS_SUCCESS;
|
||||
try {
|
||||
doWrite(outputs);
|
||||
}
|
||||
else {
|
||||
scan(contribution, inputs, outputs, chunkMonitor, false);
|
||||
catch (Exception e) {
|
||||
status = BatchMetrics.STATUS_FAILURE;
|
||||
if (rollbackClassifier.classify(e)) {
|
||||
throw e;
|
||||
}
|
||||
/*
|
||||
* If the exception is marked as no-rollback, we need to override
|
||||
* that, otherwise there's no way to write the rest of the chunk or to
|
||||
* honour the skip listener contract.
|
||||
*/
|
||||
throw new ForceRollbackForWriteSkipException(
|
||||
"Force rollback on skippable exception so that skipped item can be located.", e);
|
||||
}
|
||||
return null;
|
||||
|
||||
finally {
|
||||
stopTimer(sample, contribution.getStepExecution(), "chunk.write", status, "Chunk writing");
|
||||
}
|
||||
contribution.incrementWriteCount(outputs.size());
|
||||
}
|
||||
else {
|
||||
scan(contribution, inputs, outputs, chunkMonitor, false);
|
||||
}
|
||||
return null;
|
||||
|
||||
};
|
||||
|
||||
if (!buffering) {
|
||||
|
||||
RecoveryCallback<Object> batchRecoveryCallback = new RecoveryCallback<>() {
|
||||
RecoveryCallback<Object> batchRecoveryCallback = context -> {
|
||||
|
||||
@Override
|
||||
public Object recover(RetryContext context) throws Exception {
|
||||
Throwable e = context.getLastThrowable();
|
||||
if (outputs.size() > 1 && !rollbackClassifier.classify(e)) {
|
||||
throw new RetryException("Invalid retry state during write caused by "
|
||||
+ "exception that does not classify for rollback: ", e);
|
||||
}
|
||||
|
||||
Throwable e = context.getLastThrowable();
|
||||
if (outputs.size() > 1 && !rollbackClassifier.classify(e)) {
|
||||
throw new RetryException("Invalid retry state during write caused by "
|
||||
+ "exception that does not classify for rollback: ", e);
|
||||
Chunk<I>.ChunkIterator inputIterator = inputs.iterator();
|
||||
for (Chunk<O>.ChunkIterator outputIterator = outputs.iterator(); outputIterator.hasNext();) {
|
||||
|
||||
inputIterator.next();
|
||||
outputIterator.next();
|
||||
|
||||
checkSkipPolicy(inputIterator, outputIterator, e, contribution, true);
|
||||
if (!rollbackClassifier.classify(e)) {
|
||||
throw new RetryException(
|
||||
"Invalid retry state during recovery caused by exception that does not classify for rollback: ",
|
||||
e);
|
||||
}
|
||||
|
||||
Chunk<I>.ChunkIterator inputIterator = inputs.iterator();
|
||||
for (Chunk<O>.ChunkIterator outputIterator = outputs.iterator(); outputIterator.hasNext();) {
|
||||
|
||||
inputIterator.next();
|
||||
outputIterator.next();
|
||||
|
||||
checkSkipPolicy(inputIterator, outputIterator, e, contribution, true);
|
||||
if (!rollbackClassifier.classify(e)) {
|
||||
throw new RetryException(
|
||||
"Invalid retry state during recovery caused by exception that does not classify for rollback: ",
|
||||
e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
};
|
||||
|
||||
batchRetryTemplate.execute(retryCallback, batchRecoveryCallback,
|
||||
@@ -406,26 +388,21 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
|
||||
}
|
||||
else {
|
||||
|
||||
RecoveryCallback<Object> recoveryCallback = new RecoveryCallback<>() {
|
||||
|
||||
@Override
|
||||
public Object recover(RetryContext context) throws Exception {
|
||||
/*
|
||||
* If the last exception was not skippable we don't need to do any
|
||||
* scanning. We can just bomb out with a retry exhausted.
|
||||
*/
|
||||
if (!shouldSkip(itemWriteSkipPolicy, context.getLastThrowable(), -1)) {
|
||||
throw new ExhaustedRetryException(
|
||||
"Retry exhausted after last attempt in recovery path, but exception is not skippable.",
|
||||
context.getLastThrowable());
|
||||
}
|
||||
|
||||
inputs.setBusy(true);
|
||||
data.scanning(true);
|
||||
scan(contribution, inputs, outputs, chunkMonitor, true);
|
||||
return null;
|
||||
RecoveryCallback<Object> recoveryCallback = context -> {
|
||||
/*
|
||||
* If the last exception was not skippable we don't need to do any
|
||||
* scanning. We can just bomb out with a retry exhausted.
|
||||
*/
|
||||
if (!shouldSkip(itemWriteSkipPolicy, context.getLastThrowable(), -1)) {
|
||||
throw new ExhaustedRetryException(
|
||||
"Retry exhausted after last attempt in recovery path, but exception is not skippable.",
|
||||
context.getLastThrowable());
|
||||
}
|
||||
|
||||
inputs.setBusy(true);
|
||||
data.scanning(true);
|
||||
scan(contribution, inputs, outputs, chunkMonitor, true);
|
||||
return null;
|
||||
};
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2022 the original author or authors.
|
||||
* Copyright 2006-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,8 +31,6 @@ import org.springframework.batch.core.listener.MulticasterBatchListener;
|
||||
import org.springframework.batch.core.observability.BatchMetrics;
|
||||
import org.springframework.batch.item.Chunk;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.repeat.RepeatCallback;
|
||||
import org.springframework.batch.repeat.RepeatContext;
|
||||
import org.springframework.batch.repeat.RepeatOperations;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -126,34 +124,29 @@ public class SimpleChunkProvider<I> implements ChunkProvider<I> {
|
||||
public Chunk<I> provide(final StepContribution contribution) throws Exception {
|
||||
|
||||
final Chunk<I> inputs = new Chunk<>();
|
||||
repeatOperations.iterate(new RepeatCallback() {
|
||||
|
||||
@Override
|
||||
public RepeatStatus doInIteration(final RepeatContext context) throws Exception {
|
||||
I item = null;
|
||||
Timer.Sample sample = Timer.start(Metrics.globalRegistry);
|
||||
String status = BatchMetrics.STATUS_SUCCESS;
|
||||
try {
|
||||
item = read(contribution, inputs);
|
||||
}
|
||||
catch (SkipOverflowException e) {
|
||||
// read() tells us about an excess of skips by throwing an
|
||||
// exception
|
||||
status = BatchMetrics.STATUS_FAILURE;
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
finally {
|
||||
stopTimer(sample, contribution.getStepExecution(), status);
|
||||
}
|
||||
if (item == null) {
|
||||
inputs.setEnd();
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
inputs.add(item);
|
||||
contribution.incrementReadCount();
|
||||
return RepeatStatus.CONTINUABLE;
|
||||
repeatOperations.iterate(context -> {
|
||||
I item = null;
|
||||
Timer.Sample sample = Timer.start(Metrics.globalRegistry);
|
||||
String status = BatchMetrics.STATUS_SUCCESS;
|
||||
try {
|
||||
item = read(contribution, inputs);
|
||||
}
|
||||
|
||||
catch (SkipOverflowException e) {
|
||||
// read() tells us about an excess of skips by throwing an
|
||||
// exception
|
||||
status = BatchMetrics.STATUS_FAILURE;
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
finally {
|
||||
stopTimer(sample, contribution.getStepExecution(), status);
|
||||
}
|
||||
if (item == null) {
|
||||
inputs.setEnd();
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
inputs.add(item);
|
||||
contribution.incrementReadCount();
|
||||
return RepeatStatus.CONTINUABLE;
|
||||
});
|
||||
|
||||
return inputs;
|
||||
|
||||
Reference in New Issue
Block a user