Package org.springframework.batch.core.step.builder

Source Code of org.springframework.batch.core.step.builder.RegisterMultiListenerTests$MySkippableException

/*
* Copyright 2013-2014 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.builder;

import static org.junit.Assert.assertEquals;

import java.util.List;

import javax.sql.DataSource;

import org.junit.After;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.ItemWriteListener;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.PooledEmbeddedDataSource;
import org.springframework.batch.core.SkipListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;

/**
* Test for registering a listener class that implements different listeners interfaces
* just once in java based configuration.
*
* @author Tobias Flohre
* @author Michael Minella
*/
public class RegisterMultiListenerTests {

  @Autowired
  private JobLauncher jobLauncher;

  @Autowired
  private Job job;

  @Autowired
  private CallChecker callChecker;

  @Autowired
  private EmbeddedDatabase dataSource;

  private GenericApplicationContext context;

  @After
  public void tearDown() {
    jobLauncher = null;
    job = null;
    callChecker = null;

    if(context != null) {
      context.close();
    }
  }

  /**
   * The times the beforeChunkCalled occurs are:
   *  - Before chunk 1 (item1, item2)
   *  - Before the re-attempt of item1 (scanning)
   *  - Before the re-attempt of item2 (scanning)
   *  - Before the checking that scanning is complete
   *  - Before chunk 2 (item3, item4)
   *  - Before chunk 3 (null)
   *
   * @throws Exception
   */
  @Test
  public void testMultiListenerFaultTolerantStep() throws Exception {
    bootstrap(MultiListenerFaultTolerantTestConfiguration.class);

    JobExecution execution = jobLauncher.run(job, new JobParameters());
    assertEquals(BatchStatus.COMPLETED, execution.getStatus());
    assertEquals(1, callChecker.beforeStepCalled);
    assertEquals(6, callChecker.beforeChunkCalled);
    assertEquals(2, callChecker.beforeWriteCalled);
    assertEquals(1, callChecker.skipInWriteCalled);
  }

  @Test
  public void testMultiListenerSimpleStep() throws Exception {
    bootstrap(MultiListenerTestConfiguration.class);

    JobExecution execution = jobLauncher.run(job, new JobParameters());
    assertEquals(BatchStatus.FAILED, execution.getStatus());
    assertEquals(1, callChecker.beforeStepCalled);
    assertEquals(1, callChecker.beforeChunkCalled);
    assertEquals(1, callChecker.beforeWriteCalled);
    assertEquals(0, callChecker.skipInWriteCalled);
  }

  private void bootstrap(Class<?> configurationClass) {
    context = new AnnotationConfigApplicationContext(configurationClass);
    context.getAutowireCapableBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
  }

  public static abstract class MultiListenerTestConfigurationSupport {

    @Autowired
    protected JobBuilderFactory jobBuilders;

    @Autowired
    protected StepBuilderFactory stepBuilders;

    @Bean
    public Job testJob(){
      return jobBuilders.get("testJob")
          .start(step())
          .build();
    }

    @Bean
    public CallChecker callChecker(){
      return new CallChecker();
    }

    @Bean
    public MultiListener listener(){
      return new MultiListener(callChecker());
    }

    @Bean
    public ItemReader<String> reader(){
      return new ItemReader<String>(){

        private int count = 0;

        @Override
        public String read() throws Exception,
        UnexpectedInputException, ParseException,
        NonTransientResourceException {
          count++;

          if(count < 5) {
            return "item" + count;
          } else {
            return null;
          }
        }

      };
    }

    @Bean
    public ItemWriter<String> writer(){
      return new ItemWriter<String>(){

        @Override
        public void write(List<? extends String> items)
            throws Exception {
          if(items.contains("item2")) {
            throw new MySkippableException();
          }
        }

      };
    }

    public abstract Step step();
  }

  @Configuration
  @EnableBatchProcessing
  public static class MultiListenerFaultTolerantTestConfiguration extends MultiListenerTestConfigurationSupport{

    @Bean
    public DataSource dataSource(){
      return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder()
      .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")
      .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql")
      .setType(EmbeddedDatabaseType.HSQL)
      .build());
    }

    @Override
    @Bean
    public Step step(){
      return stepBuilders.get("step")
          .listener(listener())
          .<String,String>chunk(2)
          .reader(reader())
          .writer(writer())
          .faultTolerant()
          .skipLimit(1)
          .skip(MySkippableException.class)
          // ChunkListener registered twice for checking BATCH-2149
          .listener((ChunkListener) listener())
          .build();
    }
  }

  @Configuration
  @EnableBatchProcessing
  public static class MultiListenerTestConfiguration extends MultiListenerTestConfigurationSupport{

    @Bean
    public DataSource dataSource(){
      return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder()
      .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")
      .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql")
      .setType(EmbeddedDatabaseType.HSQL)
      .build());
    }

    @Override
    @Bean
    public Step step(){
      return stepBuilders.get("step")
          .listener(listener())
          .<String,String>chunk(2)
          .reader(reader())
          .writer(writer())
          .build();
    }
  }

  private static class CallChecker {
    int beforeStepCalled = 0;
    int beforeChunkCalled = 0;
    int beforeWriteCalled = 0;
    int skipInWriteCalled = 0;
  }

  private static class MultiListener implements StepExecutionListener, ChunkListener, ItemWriteListener<String>, SkipListener<String,String>{

    private CallChecker callChecker;

    private MultiListener(CallChecker callChecker) {
      super();
      this.callChecker = callChecker;
    }

    @Override
    public void onSkipInRead(Throwable t) {
    }

    @Override
    public void onSkipInWrite(String item, Throwable t) {
      callChecker.skipInWriteCalled++;
    }

    @Override
    public void onSkipInProcess(String item, Throwable t) {
    }

    @Override
    public void beforeWrite(List<? extends String> items) {
      callChecker.beforeWriteCalled++;
    }

    @Override
    public void afterWrite(List<? extends String> items) {
    }

    @Override
    public void onWriteError(Exception exception,
        List<? extends String> items) {
    }

    @Override
    public void beforeChunk(ChunkContext context) {
      callChecker.beforeChunkCalled++;
    }

    @Override
    public void afterChunk(ChunkContext context) {
    }

    @Override
    public void afterChunkError(ChunkContext context) {
    }

    @Override
    public void beforeStep(StepExecution stepExecution) {
      callChecker.beforeStepCalled++;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
      return null;
    }

  }

  private static class MySkippableException extends RuntimeException{

    private static final long serialVersionUID = 1L;

  }

}
TOP

Related Classes of org.springframework.batch.core.step.builder.RegisterMultiListenerTests$MySkippableException

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.