org.springframework.batch.core.step.item.SimpleChunkProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.batch.core.step.item.SimpleChunkProvider.java

Source

/*
 * Copyright 2006-2013 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.batch.core.step.item;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepListener;
import org.springframework.batch.core.listener.MulticasterBatchListener;
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;

/**
 * Simple implementation of the ChunkProvider interface that does basic chunk
 * providing from an {@link ItemReader}.
 *
 * @author Dave Syer
 * @author Michael Minella
 * @see ChunkOrientedTasklet
 */
public class SimpleChunkProvider<I> implements ChunkProvider<I> {

    protected final Log logger = LogFactory.getLog(getClass());

    protected final ItemReader<? extends I> itemReader;

    private final MulticasterBatchListener<I, ?> listener = new MulticasterBatchListener<I, Object>();

    private final RepeatOperations repeatOperations;

    public SimpleChunkProvider(ItemReader<? extends I> itemReader, RepeatOperations repeatOperations) {
        this.itemReader = itemReader;
        this.repeatOperations = repeatOperations;
    }

    /**
     * Register some {@link StepListener}s with the handler. Each will get the
     * callbacks in the order specified at the correct stage.
     *
     * @param listeners
     */
    public void setListeners(List<? extends StepListener> listeners) {
        for (StepListener listener : listeners) {
            registerListener(listener);
        }
    }

    /**
     * Register a listener for callbacks at the appropriate stages in a process.
     *
     * @param listener a {@link StepListener}
     */
    public void registerListener(StepListener listener) {
        this.listener.register(listener);
    }

    /**
     * @return the listener
     */
    protected MulticasterBatchListener<I, ?> getListener() {
        return listener;
    }

    /**
     * Surrounds the read call with listener callbacks.
     * @return item
     * @throws Exception
     */
    protected final I doRead() throws Exception {
        try {
            listener.beforeRead();
            I item = itemReader.read();
            if (item != null) {
                listener.afterRead(item);
            }
            return item;
        } catch (Exception e) {
            if (logger.isDebugEnabled()) {
                logger.debug(e.getMessage() + " : " + e.getClass().getName());
            }
            listener.onReadError(e);
            throw e;
        }
    }

    @Override
    public Chunk<I> provide(final StepContribution contribution) throws Exception {

        final Chunk<I> inputs = new Chunk<I>();
        repeatOperations.iterate(new RepeatCallback() {

            @Override
            public RepeatStatus doInIteration(final RepeatContext context) throws Exception {
                I item = null;
                try {
                    item = read(contribution, inputs);
                } catch (SkipOverflowException e) {
                    // read() tells us about an excess of skips by throwing an
                    // exception
                    return RepeatStatus.FINISHED;
                }
                if (item == null) {
                    inputs.setEnd();
                    return RepeatStatus.FINISHED;
                }
                inputs.add(item);
                contribution.incrementReadCount();
                return RepeatStatus.CONTINUABLE;
            }

        });

        return inputs;

    }

    @Override
    public void postProcess(StepContribution contribution, Chunk<I> chunk) {
        // do nothing
    }

    /**
     * Delegates to {@link #doRead()}. Subclasses can add additional behaviour
     * (e.g. exception handling).
     *
     * @param contribution the current step execution contribution
     * @param chunk the current chunk
     * @return a new item for processing
     *
     * @throws SkipOverflowException if specifically the chunk is accumulating
     * too much data (e.g. skips) and it wants to force a commit.
     *
     * @throws Exception if there is a generic issue
     */
    protected I read(StepContribution contribution, Chunk<I> chunk) throws SkipOverflowException, Exception {
        return doRead();
    }

}