Package org.springframework.batch.repeat.support

Source Code of org.springframework.batch.repeat.support.Chunker

/*
* Copyright 2006-2007 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.repeat.support;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.repeat.RepeatCallback;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.repeat.callback.NestedRepeatCallback;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

/**
* Test various approaches to chunking of a batch. Not really a unit test, but
* it should be fast.
*
* @author Dave Syer
*
*/
public class ChunkedRepeatTests extends AbstractTradeBatchTests {

  int count = 0;

  /**
   * Chunking using a dedicated TerminationPolicy. Transactions would be laid
   * on at the level of chunkTemplate.execute() or the surrounding callback.
   *
   * @throws Exception
   */
  @Test
  public void testChunkedBatchWithTerminationPolicy() throws Exception {

    RepeatTemplate repeatTemplate = new RepeatTemplate();
    final RepeatCallback callback = new ItemReaderRepeatCallback<Trade>(provider, processor);

    final RepeatTemplate chunkTemplate = new RepeatTemplate();
    // The policy is resettable so we only have to resolve this dependency
    // once
    chunkTemplate.setCompletionPolicy(new SimpleCompletionPolicy(2));

    RepeatStatus result = repeatTemplate.iterate(new NestedRepeatCallback(chunkTemplate, callback) {

            @Override
      public RepeatStatus doInIteration(RepeatContext context) throws Exception {
        count++; // for test assertion
        return super.doInIteration(context);
      }

    });

    assertEquals(NUMBER_OF_ITEMS, processor.count);
    // The chunk executes 3 times because the last one
    // returns false. We terminate the main batch when
    // we encounter a partially empty chunk.
    assertEquals(3, count);
    assertFalse(result.isContinuable());

  }

  /**
   * Chunking with an asynchronous taskExecutor in the chunks. Transactions
   * have to be at the level of the business callback.
   *
   * @throws Exception
   */
  @Test
  public void testAsynchronousChunkedBatchWithCompletionPolicy() throws Exception {

    RepeatTemplate repeatTemplate = new RepeatTemplate();
    final RepeatCallback callback = new ItemReaderRepeatCallback<Trade>(provider, processor);

    final TaskExecutorRepeatTemplate chunkTemplate = new TaskExecutorRepeatTemplate();
    // The policy is resettable so we only have to resolve this dependency
    // once
    chunkTemplate.setCompletionPolicy(new SimpleCompletionPolicy(2));
    chunkTemplate.setTaskExecutor(new SimpleAsyncTaskExecutor());

    RepeatStatus result = repeatTemplate.iterate(new NestedRepeatCallback(chunkTemplate, callback) {

            @Override
      public RepeatStatus doInIteration(RepeatContext context) throws Exception {
        count++; // for test assertion
        return super.doInIteration(context);
      }

    });

    assertEquals(NUMBER_OF_ITEMS, processor.count);
    assertFalse(result.isContinuable());
    assertTrue("Expected at least 3 chunks but found: "+count, count>=3);

  }

  /**
   * Explicit chunking of input data. Transactions would be laid on at the
   * level of template.execute().
   *
   * @throws Exception
   */
  @Test
  public void testChunksWithTruncatedItemProvider() throws Exception {

    RepeatTemplate template = new RepeatTemplate();

    // This pattern would work with an asynchronous callback as well
    // (but non-transactional in that case).

    class Chunker {
      boolean ready = false;

      int count = 0;

      void set() {
        ready = true;
      }

      boolean ready() {
        return ready;
      }

      boolean first() {
        return count == 0;
      }

      void reset() {
        count = 0;
        ready = false;
      }

      void increment() {
        count++;
      }
    }

    final Chunker chunker = new Chunker();

    while (!chunker.ready()) {

      ItemReader<Trade> truncated = new ItemReader<Trade>() {
        int count = 0;

                @Override
        public Trade read() throws Exception {
          if (count++ < 2)
            return provider.read();
          return null;
        }
      };
      chunker.reset();
      template.iterate(new ItemReaderRepeatCallback<Trade>(truncated, processor) {

                @Override
        public RepeatStatus doInIteration(RepeatContext context) throws Exception {
          RepeatStatus result = super.doInIteration(context);
          if (!result.isContinuable() && chunker.first()) {
            chunker.set();
          }
          chunker.increment();
          return result;
        }

      });

    }

    assertEquals(NUMBER_OF_ITEMS, processor.count);

  }

}
TOP

Related Classes of org.springframework.batch.repeat.support.Chunker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.