List of usage examples for org.springframework.batch.core.step.item Chunk getItems
public List<W> getItems()
From source file:es.fcs.batch.integration.chunk.MyRemoteChunkHandlerFactoryBean.java
/** * Replace the chunk processor in the tasklet provided with one that can act as a master in the Remote Chunking * pattern.// w ww . ja va2 s .c o m * * @param tasklet a ChunkOrientedTasklet * @param chunkWriter an ItemWriter that can send the chunks to remote workers * @param stepContributionSource a StepContributionSource used to gather results from the workers */ private void replaceChunkProcessor(ChunkOrientedTasklet<?> tasklet, ItemWriter<T> chunkWriter, final StepContributionSource stepContributionSource) { setField(tasklet, "chunkProcessor", new SimpleChunkProcessor<T, T>(new PassThroughItemProcessor<T>(), chunkWriter) { /** * */ private static final long serialVersionUID = -8914556774351841413L; @Override protected void write(StepContribution contribution, Chunk<T> inputs, Chunk<T> outputs) throws Exception { doWrite(outputs.getItems()); // Do not update the step contribution until the chunks are // actually processed updateStepContribution(contribution, stepContributionSource); } }); }
From source file:org.springframework.batch.core.jsr.step.item.JsrChunkProcessor.java
/** * Responsible for the writing portion of the chunking loop. In this implementation, delegates to the * {{@link #doPersist(StepContribution, Chunk)}. * * @param contribution a {@link StepContribution} * @param chunk a {@link Chunk}/*w w w . j a v a2 s. com*/ * @throws Exception */ protected void persist(final StepContribution contribution, final Chunk<O> chunk) throws Exception { doPersist(contribution, chunk); contribution.incrementWriteCount(chunk.getItems().size()); }
From source file:org.springframework.batch.core.jsr.step.item.JsrChunkProcessor.java
/** * Implements writing and all related listener calls * * @param contribution a {@link StepContribution} * @param chunk a {@link Chunk}//from w ww . j a v a 2 s . co m * @throws Exception */ protected final void doPersist(final StepContribution contribution, final Chunk<O> chunk) throws Exception { try { List<O> items = chunk.getItems(); listener.beforeWrite(items); itemWriter.write(items); listener.afterWrite(items); } catch (Exception e) { listener.onWriteError(e, chunk.getItems()); throw e; } }
From source file:org.springframework.batch.core.jsr.step.item.JsrFaultTolerantChunkProcessor.java
/** * Adds retry and skip logic to the write phase of the chunk loop. * * @param contribution a {@link StepContribution} * @param chunk a {@link Chunk}//from w w w . jav a2s .com * @throws Exception */ @Override protected void persist(final StepContribution contribution, final Chunk<O> chunk) throws Exception { RetryCallback<Object, Exception> retryCallback = new RetryCallback<Object, Exception>() { @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public Object doWithRetry(RetryContext context) throws Exception { chunkMonitor.setChunkSize(chunk.size()); try { doPersist(contribution, chunk); } catch (Exception e) { if (shouldSkip(skipPolicy, e, contribution.getStepSkipCount())) { // Per section 9.2.7 of JSR-352, the SkipListener receives all the items within the chunk ((MulticasterBatchListener) getListener()).onSkipInWrite(chunk.getItems(), e); } else { getListener().onRetryWriteException((List<Object>) chunk.getItems(), e); 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); } contribution.incrementWriteCount(chunk.size()); return null; } }; RecoveryCallback<Object> recoveryCallback = new RecoveryCallback<Object>() { @Override public O recover(RetryContext context) throws Exception { Throwable e = context.getLastThrowable(); if (shouldSkip(skipPolicy, e, contribution.getStepSkipCount())) { contribution.incrementWriteSkipCount(); logger.debug("Skipping after failed write", 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 write", e); } return null; } } }; batchRetryTemplate.execute(retryCallback, recoveryCallback); }
From source file:org.springframework.batch.core.step.item.AlmostStatefulRetryChunkTests.java
/** * @param chunk/*from w w w .ja va 2s .c o m*/ * @throws Exception */ private void statefulRetry(Chunk<String> chunk) throws Exception { if (retryAttempts <= retryLimit) { try { // N.B. a classic stateful retry goes straight to recovery here logger.debug(String.format("Retry (attempts=%d) chunk: %s", retryAttempts, chunk)); doWrite(chunk.getItems()); retryAttempts = 0; } catch (Exception e) { retryAttempts++; // stateful retry always rethrow throw e; } } else { try { logger.debug(String.format("Recover (attempts=%d) chunk: %s", retryAttempts, chunk)); recover(chunk); } finally { retryAttempts = 0; } } // recovery return; }
From source file:org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.java
@Override protected Chunk<O> getAdjustedOutputs(Chunk<I> inputs, Chunk<O> outputs) { @SuppressWarnings("unchecked") UserData<O> data = (UserData<O>) inputs.getUserData(); Chunk<O> previous = data.getOutputs(); Chunk<O> next = new Chunk<O>(outputs.getItems(), previous.getSkips()); next.setBusy(previous.isBusy());/*from w w w. j a va2s . c om*/ // Remember for next time if there are skips accumulating data.setOutputs(next); return next; }
From source file:org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.java
@Override protected Chunk<O> transform(final StepContribution contribution, Chunk<I> inputs) throws Exception { Chunk<O> outputs = new Chunk<O>(); @SuppressWarnings("unchecked") final UserData<O> data = (UserData<O>) inputs.getUserData(); final Chunk<O> cache = data.getOutputs(); final Iterator<O> cacheIterator = cache.isEmpty() ? null : new ArrayList<O>(cache.getItems()).iterator(); final AtomicInteger count = new AtomicInteger(0); // final int scanLimit = processorTransactional && data.scanning() ? 1 : // 0;//from w ww . j a v a2 s.c o m for (final Chunk<I>.ChunkIterator iterator = inputs.iterator(); iterator.hasNext();) { final I item = iterator.next(); RetryCallback<O, Exception> retryCallback = new RetryCallback<O, Exception>() { @Override public O doWithRetry(RetryContext context) throws Exception { O output = null; try { count.incrementAndGet(); 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) { 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); } } if (output == null) { // No need to re-process filtered items iterator.remove(); } return output; } }; RecoveryCallback<O> recoveryCallback = new RecoveryCallback<O>() { @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; } 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, new DefaultRetryState(getInputKey(item), rollbackClassifier)); if (output != null) { outputs.add(output); } /* * We only want to process the first item if there is a scan for a * failed item. */ if (data.scanning()) { while (cacheIterator != null && cacheIterator.hasNext()) { outputs.add(cacheIterator.next()); } // Only process the first item if scanning break; } } return outputs; }
From source file:org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.java
@Override protected void write(final StepContribution contribution, final Chunk<I> inputs, final Chunk<O> outputs) throws Exception { @SuppressWarnings("unchecked") final UserData<O> data = (UserData<O>) inputs.getUserData(); final AtomicReference<RetryContext> contextHolder = new AtomicReference<RetryContext>(); RetryCallback<Object, Exception> retryCallback = new RetryCallback<Object, Exception>() { @Override//from www .j a v a 2s .c o m public Object doWithRetry(RetryContext context) throws Exception { contextHolder.set(context); if (!data.scanning()) { chunkMonitor.setChunkSize(inputs.size()); try { doWrite(outputs.getItems()); } catch (Exception e) { 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); } contribution.incrementWriteCount(outputs.size()); } else { scan(contribution, inputs, outputs, chunkMonitor, false); } return null; } }; if (!buffering) { RecoveryCallback<Object> batchRecoveryCallback = new RecoveryCallback<Object>() { @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); } 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; } }; batchRetryTemplate.execute(retryCallback, batchRecoveryCallback, BatchRetryTemplate.createState(getInputKeys(inputs), rollbackClassifier)); } else { RecoveryCallback<Object> recoveryCallback = new RecoveryCallback<Object>() { @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; } }; if (logger.isDebugEnabled()) { logger.debug("Attempting to write: " + inputs); } try { batchRetryTemplate.execute(retryCallback, recoveryCallback, new DefaultRetryState(inputs, rollbackClassifier)); } catch (Exception e) { RetryContext context = contextHolder.get(); if (!batchRetryTemplate.canRetry(context)) { /* * BATCH-1761: we need advance warning of the scan about to * start in the next transaction, so we can change the * processing behaviour. */ data.scanning(true); } throw e; } } callSkipListeners(inputs, outputs); }
From source file:org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.java
private List<?> getInputKeys(final Chunk<I> inputs) { if (keyGenerator == null) { return inputs.getItems(); }//from w w w . ja va2 s . c o m List<Object> keys = new ArrayList<Object>(); for (I item : inputs.getItems()) { keys.add(keyGenerator.getKey(item)); } return keys; }
From source file:org.springframework.batch.integration.chunk.RemoteChunkHandlerFactoryBean.java
/** * Replace the chunk processor in the tasklet provided with one that can act as a master in the Remote Chunking * pattern.//from ww w.j a v a 2s. c om * * @param tasklet a ChunkOrientedTasklet * @param chunkWriter an ItemWriter that can send the chunks to remote workers * @param stepContributionSource a StepContributionSource used to gather results from the workers */ private void replaceChunkProcessor(ChunkOrientedTasklet<?> tasklet, ItemWriter<T> chunkWriter, final StepContributionSource stepContributionSource) { setField(tasklet, "chunkProcessor", new SimpleChunkProcessor<T, T>(new PassThroughItemProcessor<T>(), chunkWriter) { @Override protected void write(StepContribution contribution, Chunk<T> inputs, Chunk<T> outputs) throws Exception { doWrite(outputs.getItems()); // Do not update the step contribution until the chunks are // actually processed updateStepContribution(contribution, stepContributionSource); } }); }