@Override protected Tasklet createTasklet() { Assert.state(reader != null, "ItemReader must be provided"); Assert.state(writer != null, "ItemWriter must be provided"); RepeatOperations repeatOperations = createChunkOperations(); SimpleChunkProvider<I> chunkProvider = new SimpleChunkProvider<>(getReader(), repeatOperations); SimpleChunkProcessor<I, O> chunkProcessor = new SimpleChunkProcessor<>(getProcessor(), getWriter()); chunkProvider.setListeners(new ArrayList<>(itemListeners)); chunkProcessor.setListeners(new ArrayList<>(itemListeners)); ChunkOrientedTasklet<I> tasklet = new ChunkOrientedTasklet<>(chunkProvider, chunkProcessor); tasklet.setBuffering(!readerTransactionalQueue); return tasklet; }
/** * Register some {@link StepListener}s with the handler. Each will get the * callbacks in the order specified at the correct stage. * * @param listeners list of {@link StepListener} instances. */ public void setListeners(List<? extends StepListener> listeners) { for (StepListener listener : listeners) { registerListener(listener); } }
/** * Surrounds the actual write call with listener callbacks. * * @param items list of items to be written. * @throws Exception thrown if error occurs. */ protected final void doWrite(List<O> items) throws Exception { if (itemWriter == null) { return; } try { listener.beforeWrite(items); writeItems(items); doAfterWrite(items); } catch (Exception e) { doOnWriteError(e, items); throw e; } }
@Override public final void process(StepContribution contribution, Chunk<I> inputs) throws Exception { // Allow temporary state to be stored in the user data field initializeUserData(inputs); // If there is no input we don't have to do anything more if (isComplete(inputs)) { return; } // Make the transformation, calling remove() on the inputs iterator if // any items are filtered. Might throw exception and cause rollback. Chunk<O> outputs = transform(contribution, inputs); // Adjust the filter count based on available data contribution.incrementFilterCount(getFilterCount(inputs, outputs)); // Adjust the outputs if necessary for housekeeping purposes, and then // write them out... write(contribution, inputs, getAdjustedOutputs(inputs, outputs)); }
/** * Surrounds the actual write call with listener callbacks. * * @param items * @throws Exception */ protected final void doWrite(List<O> items) throws Exception { if (itemWriter==null) { return; } try { listener.beforeWrite(items); writeItems(items); doAfterWrite(items); } catch (Exception e) { listener.onWriteError(e, items); throw e; } }
/** * Creates a {@link PassThroughItemProcessor} and uses it to create an * instance of {@link Tasklet}. */ public TestingChunkOrientedTasklet(ItemReader<T> itemReader, ItemProcessor<T, T> itemProcessor, ItemWriter<T> itemWriter, RepeatOperations repeatOperations) { super(new SimpleChunkProvider<>(itemReader, repeatOperations), new SimpleChunkProcessor<>( itemProcessor, itemWriter)); }
SkipListener.class)); chunkProcessor.setListeners(BatchListenerFactoryHelper.<ItemProcessListener<T, S>> getListeners(listeners, ItemProcessListener.class)); chunkProcessor.setListeners(BatchListenerFactoryHelper.<ItemWriteListener<S>> getListeners(listeners, ItemWriteListener.class)); chunkProcessor.setListeners(BatchListenerFactoryHelper.<SkipListener<T, S>> getListeners(listeners, SkipListener.class)); if (listener instanceof SkipListener<?,?>) { chunkProvider.registerListener(listener); chunkProcessor.registerListener(listener); chunkProcessor.registerListener(listener);
@Bean @Profile("slave") @ServiceActivator(inputChannel = "inboundRequests", outputChannel = "outboundReplies") public ChunkProcessorChunkHandler chunkProcessorChunkHandler(ItemProcessor<Customer, Customer> itemProcessor, ItemWriter<Customer> itemWriter) throws Exception { SimpleChunkProcessor chunkProcessor = new SimpleChunkProcessor<>(itemProcessor, itemWriter); chunkProcessor.afterPropertiesSet(); ChunkProcessorChunkHandler<Customer> chunkHandler = new ChunkProcessorChunkHandler<>(); chunkHandler.setChunkProcessor(chunkProcessor); chunkHandler.afterPropertiesSet(); return chunkHandler; }
protected Chunk<O> transform(StepContribution contribution, Chunk<I> inputs) throws Exception { Chunk<O> outputs = new Chunk<>(); for (Chunk<I>.ChunkIterator iterator = inputs.iterator(); iterator.hasNext();) { final I item = iterator.next(); O output; try { output = doProcess(item); } catch (Exception e) { /* * For a simple chunk processor (no fault tolerance) we are done * here, so prevent any more processing of these inputs. */ inputs.clear(); throw e; } if (output != null) { outputs.add(output); } else { iterator.remove(); } } return outputs; }
/** * Simple implementation delegates to the {@link #doWrite(List)} method and * increments the write count in the contribution. Subclasses can handle * more complicated scenarios, e.g.with fault tolerance. If output items are * skipped they should be removed from the inputs as well. * * @param contribution the current step contribution * @param inputs the inputs that gave rise to the outputs * @param outputs the outputs to write * @throws Exception if there is a problem */ protected void write(StepContribution contribution, Chunk<I> inputs, Chunk<O> outputs) throws Exception { try { doWrite(outputs.getItems()); } catch (Exception e) { /* * For a simple chunk processor (no fault tolerance) we are done * here, so prevent any more processing of these inputs. */ inputs.clear(); throw e; } contribution.incrementWriteCount(outputs.size()); }
@Override public final void process(StepContribution contribution, Chunk<I> inputs) throws Exception { // Allow temporary state to be stored in the user data field initializeUserData(inputs); // If there is no input we don't have to do anything more if (isComplete(inputs)) { return; } // Make the transformation, calling remove() on the inputs iterator if // any items are filtered. Might throw exception and cause rollback. Chunk<O> outputs = transform(contribution, inputs); // Adjust the filter count based on available data contribution.incrementFilterCount(getFilterCount(inputs, outputs)); // Adjust the outputs if necessary for housekeeping purposes, and then // write them out... write(contribution, inputs, getAdjustedOutputs(inputs, outputs)); }
/** * Create an {@link IntegrationFlow} with a {@link ChunkProcessorChunkHandler} * configured as a service activator listening to the input channel and replying * on the output channel. * * @return the integration flow */ @SuppressWarnings({"unchecked", "rawtypes"}) public IntegrationFlow build() { Assert.notNull(this.itemWriter, "An ItemWriter must be provided"); Assert.notNull(this.inputChannel, "An InputChannel must be provided"); Assert.notNull(this.outputChannel, "An OutputChannel must be provided"); if(this.itemProcessor == null) { this.itemProcessor = new PassThroughItemProcessor(); } SimpleChunkProcessor<I, O> chunkProcessor = new SimpleChunkProcessor<>(this.itemProcessor, this.itemWriter); ChunkProcessorChunkHandler<I> chunkProcessorChunkHandler = new ChunkProcessorChunkHandler<>(); chunkProcessorChunkHandler.setChunkProcessor(chunkProcessor); return IntegrationFlows .from(this.inputChannel) .handle(chunkProcessorChunkHandler, SERVICE_ACTIVATOR_METHOD_NAME) .channel(this.outputChannel) .get(); }
protected Chunk<O> transform(StepContribution contribution, Chunk<I> inputs) throws Exception { Chunk<O> outputs = new Chunk<O>(); for (Chunk<I>.ChunkIterator iterator = inputs.iterator(); iterator.hasNext();) { final I item = iterator.next(); O output = doProcess(item); if (output != null) { outputs.add(output); } else { iterator.remove(); } } return outputs; }
/** * Simple implementation delegates to the {@link #doWrite(List)} method and * increments the write count in the contribution. Subclasses can handle * more complicated scenarios, e.g.with fault tolerance. If output items are * skipped they should be removed from the inputs as well. * * @param contribution the current step contribution * @param inputs the inputs that gave rise to the ouputs * @param outputs the outputs to write * @throws Exception if there is a problem */ protected void write(StepContribution contribution, Chunk<I> inputs, Chunk<O> outputs) throws Exception { doWrite(outputs.getItems()); contribution.incrementWriteCount(outputs.size()); }
@Override public final void process(StepContribution contribution, Chunk<I> inputs) throws Exception { // Allow temporary state to be stored in the user data field initializeUserData(inputs); // If there is no input we don't have to do anything more if (isComplete(inputs)) { return; } // Make the transformation, calling remove() on the inputs iterator if // any items are filtered. Might throw exception and cause rollback. Chunk<O> outputs = transform(contribution, inputs); // Adjust the filter count based on available data contribution.incrementFilterCount(getFilterCount(inputs, outputs)); // Adjust the outputs if necessary for housekeeping purposes, and then // write them out... write(contribution, inputs, getAdjustedOutputs(inputs, outputs)); }
/** * Surrounds the actual write call with listener callbacks. * * @param items list of items to be written. * @throws Exception thrown if error occurs. */ protected final void doWrite(List<O> items) throws Exception { if (itemWriter == null) { return; } try { listener.beforeWrite(items); writeItems(items); doAfterWrite(items); } catch (Exception e) { doOnWriteError(e, items); throw e; } }
@Override protected Tasklet createTasklet() { Assert.state(reader != null, "ItemReader must be provided"); Assert.state(processor != null || writer != null, "ItemWriter or ItemProcessor must be provided"); RepeatOperations repeatOperations = createChunkOperations(); SimpleChunkProvider<I> chunkProvider = new SimpleChunkProvider<I>(reader, repeatOperations); SimpleChunkProcessor<I, O> chunkProcessor = new SimpleChunkProcessor<I, O>(processor, writer); chunkProvider.setListeners(new ArrayList<StepListener>(itemListeners)); chunkProcessor.setListeners(new ArrayList<StepListener>(itemListeners)); ChunkOrientedTasklet<I> tasklet = new ChunkOrientedTasklet<I>(chunkProvider, chunkProcessor); tasklet.setBuffering(!readerTransactionalQueue); return tasklet; }
/** * Register some {@link StepListener}s with the handler. Each will get the * callbacks in the order specified at the correct stage. * * @param listeners list of {@link StepListener} instances. */ public void setListeners(List<? extends StepListener> listeners) { for (StepListener listener : listeners) { registerListener(listener); } }
/** * Extension point for creating appropriate {@link ChunkProcessor}. Return * value must subclass {@link SimpleChunkProcessor} due to listener * registration. */ protected SimpleChunkProcessor<T, S> configureChunkProcessor() { return new SimpleChunkProcessor<T, S>(itemProcessor, itemWriter); }
protected Chunk<O> transform(StepContribution contribution, Chunk<I> inputs) throws Exception { Chunk<O> outputs = new Chunk<O>(); for (Chunk<I>.ChunkIterator iterator = inputs.iterator(); iterator.hasNext();) { final I item = iterator.next(); O output; try { output = doProcess(item); } catch (Exception e) { /* * For a simple chunk processor (no fault tolerance) we are done * here, so prevent any more processing of these inputs. */ inputs.clear(); throw e; } if (output != null) { outputs.add(output); } else { iterator.remove(); } } return outputs; }