Package org.springframework.batch.core.step.tasklet

Source Code of org.springframework.batch.core.step.tasklet.AsyncTaskletStepTests

/*
* 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.tasklet;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.JobRepositorySupport;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemStreamSupport;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.batch.item.support.PassThroughItemProcessor;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.util.StringUtils;

public class AsyncTaskletStepTests {

  private static Log logger = LogFactory.getLog(AsyncTaskletStepTests.class);

  private List<String> processed = new CopyOnWriteArrayList<String>();

  private TaskletStep step;

  private int throttleLimit = 20;

  ItemWriter<String> itemWriter = new ItemWriter<String>() {
    @Override
    public void write(List<? extends String> data) throws Exception {
      // Thread.sleep(100L);
      logger.info("Items: " + data);
      processed.addAll(data);
      if (data.contains("fail")) {
        throw new RuntimeException("Planned");
      }
    }
  };

  private JobRepository jobRepository;

  private List<String> items;

  private int concurrencyLimit = 300;

  private ItemProcessor<String, String> itemProcessor = new PassThroughItemProcessor<String>();

  private void setUp() throws Exception {

    step = new TaskletStep("stepName");

    ResourcelessTransactionManager transactionManager = new ResourcelessTransactionManager();
    step.setTransactionManager(transactionManager);

    RepeatTemplate chunkTemplate = new RepeatTemplate();
    chunkTemplate.setCompletionPolicy(new SimpleCompletionPolicy(2));
    step.setTasklet(new TestingChunkOrientedTasklet<String>(new ListItemReader<String>(items), itemProcessor, itemWriter,
        chunkTemplate));

    jobRepository = new JobRepositorySupport();
    step.setJobRepository(jobRepository);

    TaskExecutorRepeatTemplate template = new TaskExecutorRepeatTemplate();
    template.setThrottleLimit(throttleLimit);
    SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
    taskExecutor.setConcurrencyLimit(concurrencyLimit);
    template.setTaskExecutor(taskExecutor);
    step.setStepOperations(template);

    step.registerStream(new ItemStreamSupport() {
      private int count = 0;

      @Override
      public void update(ExecutionContext executionContext) {
                                super.update(executionContext);
        executionContext.putInt("counter", count++);
      }
    });

  }

  /**
   * StepExecution should be updated after every chunk commit.
   */
  @Test
  public void testStepExecutionUpdates() throws Exception {

    items = new ArrayList<String>(Arrays.asList(StringUtils
        .commaDelimitedListToStringArray("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25")));

    setUp();

    JobExecution jobExecution = jobRepository.createJobExecution("JOB", new JobParameters());
    StepExecution stepExecution = jobExecution.createStepExecution(step.getName());

    step.execute(stepExecution);

    assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
//    assertEquals(25, stepExecution.getReadCount());
//    assertEquals(25, processed.size());
    assertTrue(stepExecution.getReadCount() >= 25);
    assertTrue(processed.size() >= 25);

    // System.err.println(stepExecution.getCommitCount());
    // System.err.println(processed);
    // Check commit count didn't spin out of control waiting for other
    // threads to finish...
    assertTrue("Not enough commits: " + stepExecution.getCommitCount(),
        stepExecution.getCommitCount() > processed.size() / 2);
    assertTrue("Too many commits: " + stepExecution.getCommitCount(),
        stepExecution.getCommitCount() <= processed.size() / 2 + throttleLimit + 1);

  }

  /**
   * StepExecution should fail immediately on error.
   */
  @Test
  public void testStepExecutionFails() throws Exception {

    throttleLimit = 1;
    concurrencyLimit = 1;
    items = Arrays.asList("one", "fail", "three", "four");
    setUp();

    JobExecution jobExecution = jobRepository.createJobExecution("JOB", new JobParameters());
    StepExecution stepExecution = jobExecution.createStepExecution(step.getName());

    step.execute(stepExecution);

    assertEquals(BatchStatus.FAILED, stepExecution.getStatus());
    assertEquals(2, stepExecution.getReadCount());
    assertEquals(2, processed.size());

  }

  /**
   * StepExecution should fail immediately on error in processor.
   */
  @Test
  public void testStepExecutionFailsWithProcessor() throws Exception {

    throttleLimit = 1;
    concurrencyLimit = 1;
    items = Arrays.asList("one", "barf", "three", "four");
    itemProcessor = new ItemProcessor<String, String>() {
      @Override
      public String process(String item) throws Exception {
        logger.info("Item: "+item);
        processed.add(item);
        if (item.equals("barf")) {
          throw new RuntimeException("Planned processor error");
        }
        return item;
      }
    };
    setUp();

    JobExecution jobExecution = jobRepository.createJobExecution("JOB", new JobParameters());
    StepExecution stepExecution = jobExecution.createStepExecution(step.getName());

    step.execute(stepExecution);

    assertEquals(BatchStatus.FAILED, stepExecution.getStatus());
    assertEquals(2, stepExecution.getReadCount());
    assertEquals(2, processed.size());

  }

  /**
   * StepExecution should fail immediately on error.
   */
  @Test
  public void testStepExecutionFailsOnLastItem() throws Exception {

    throttleLimit = 1;
    concurrencyLimit = 1;
    items = Arrays.asList("one", "two", "three", "fail");
    setUp();

    JobExecution jobExecution = jobRepository.createJobExecution("JOB", new JobParameters());
    StepExecution stepExecution = jobExecution.createStepExecution(step.getName());

    step.execute(stepExecution);

    assertEquals(BatchStatus.FAILED, stepExecution.getStatus());
    assertEquals(4, stepExecution.getReadCount());
    assertEquals(4, processed.size());

  }

}
TOP

Related Classes of org.springframework.batch.core.step.tasklet.AsyncTaskletStepTests

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.