Home > Back-end >  Failed to initialize the reader when testing a step scoped JdbcCursorItemReader
Failed to initialize the reader when testing a step scoped JdbcCursorItemReader

Time:12-10

I get this error while testing my reader:

Failed to initialize the reader
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
    at app//org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:153)
    at app//org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader$$FastClassBySpringCGLIB$$ebb633d0.invoke(<generated>)
    at app//org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at app//org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at app//org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at app//org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at app//org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137)
    at app//org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
    at app//org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at app//org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at app//org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at app//org.springframework.batch.item.database.JdbcCursorItemReader$$EnhancerBySpringCGLIB$$403e222f.open(<generated>)
    at app//com.europcar.tokenization.step.reader.BankCardReaderTest.lambda$readAll$0(BankCardReaderTest.java:131)
    at app//org.springframework.batch.test.StepScopeTestUtils.doInStepScope(StepScopeTestUtils.java:38)
    at app//com.europcar.tokenization.step.reader.BankCardReaderTest.readAll(BankCardReaderTest.java:127)
    at app//com.europcar.tokenization.step.reader.BankCardReaderTest.readTest(BankCardReaderTest.java:120)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at [email protected]/java.lang.reflect.Method.invoke(Method.java:568)
    at app//org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at app//org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at app//org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at app//org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at app//org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at app//org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at app//org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at [email protected]/java.util.ArrayList.forEach(ArrayList.java:1511)
    at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at [email protected]/java.util.ArrayList.forEach(ArrayList.java:1511)
    at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at [email protected]/java.lang.reflect.Method.invoke(Method.java:568)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: org.springframework.jdbc.BadSqlGrammarException: Executing query; bad SQL grammar [select field1,field2
       field3,
       field4,
       field5
from   MYDB.MYTABLE wct]; nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "MYTABLE"
Table "MYTABLE" not found;

how can I avoid this error? when I debug I go throw the ReaderConfig class and initiliaze reader when context is created, but when come to the test reader is not initialized!

some one can help me?

this is my test class,this is my test config for Reader and job Config. I set an H2 database withs properties file above

@ActiveProfiles("test") @RunWith(SpringRunner.class) @PropertySource(ignoreResourceNotFound = true, value = "classpath:application-test.properties") @SpringBootTest @EnableAutoConfiguration @ContextConfiguration(classes = { MyFunctionJobConfiguration.class, ReaderConfig.class}) @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) @DirtiesContext(classMode
= ClassMode.AFTER_CLASS) public class `MyEntity`ReaderTest {
     @Autowired   private JdbcCursorItemReader<MyEntity> MyEntityReader;

  @Autowired   private DataSource dataSource;
     StepExecution stepExecution;

  private static final Logger LOGGER = LoggerFactory.getLogger("TEST_LOGGER");

  private JobParameters defaultJobParameters() {
    JobParameters params = new JobParametersBuilder()
      .addString("JobID", String.valueOf(System.currentTimeMillis()))
      .toJobParameters();
    return params;   }   @BeforeEach   public void setUp() throws Exception {   }   public StepExecution getStepExecution() {
    StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(defaultJobParameters());
    return stepExecution;   }   @Test   @Transactional   void readTest() throws Exception {
    List<MyEntity> MyEntities = readAll();
    LOGGER.info("result of read : bank card  ={}", MyEntities);
    assertNotNull(MyEntities);   }

  private List<MyEntity> readAll() throws Exception {
    // build step execution context
    return StepScopeTestUtils.doInStepScope(
      getStepExecution(),
      () -> {
        // init reader
        MyEntityReader.open(stepExecution.getExecutionContext());
        List<MyEntity> items = new ArrayList<>();
        MyEntity MyEntity1;
        while ((MyEntity1 = MyEntityReader.read()) != null) {
          items.add(MyEntity1);
        }
        MyEntityReader.close();
        return items;
      });   } }


@Profile("test")
@Configuration
public class ReaderConfig {

  @Autowired
  private DataSource dataSource;

  private MyEntityRowMapper MyEntityRowMapper = new MyEntityRowMapper();

  private static final String SQL_FILE = "extract_entities_test.sql";
  Integer maxCardsNumber;
  public static final String MODULO_LABEL = ":modulo";
  public static final String GRID_SIZE_LABEL = ":gridSize";
  @Bean
  @Primary
  @StepScope
  public JdbcCursorItemReader<MyEntity> MyEntityReader() throws IOException {
    return initMyEntityReader(1,1);
  }

  @SqlGroup
    ({
      @Sql(scripts={"classpath:create-tables.sql"}),
      @Sql(scripts={"classpath:init_MyEntity_data.sql"})
    })
  public JdbcCursorItemReader<MyEntity> initMyEntityReader(int modulo, int gridSize) throws IOException {
    JdbcCursorItemReader<MyEntity> cursorItemReader = new JdbcCursorItemReader<>();
    ClassPathResource resource = new ClassPathResource(SQL_FILE);
    BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
    String query = FileCopyUtils.copyToString(reader);
    query = query.replace(MODULO_LABEL, String.valueOf(modulo));
    query = query.replace(GRID_SIZE_LABEL, String.valueOf(gridSize));
    cursorItemReader.setSql(query);
    final int partitionSize = 10 / gridSize;
    cursorItemReader.setMaxItemCount(partitionSize);
    cursorItemReader.setDataSource(dataSource);
    cursorItemReader.setRowMapper(MyEntityRowMapper);
    return cursorItemReader;
  }
}

@Configuration
@EnableBatchProcessing
@RefreshScope
public class MyFunctionJobConfiguration {

    @Autowired
    public JobBuilderFactory jobBuilderFactory;
    @Autowired
    public StepBuilderFactory stepBuilderFactory;
    @Autowired
    JdbcCursorItemReader<MyEntity> reader;
    @Value("${max-number-card-to-process}")
    private Integer MAX_NUMBER_CARD;
    @Value("${chunck-size:10}")
    private int chunckSize;
    @Value("${grid-size:1}")
    private int gridSize;

    private final static String JOB_DISABLED = "job is disabled, check the configuration file !";
    @Value("${job.enabled}")
    private boolean batchIsEnabled;
    private static final Logger LOGGER = LoggerFactory.getLogger("FUNCTIONAL_LOGGER");

    @Bean
    @StepScope
    @RefreshScope
    public MyEntityWriter writer() {
        return new MyEntityWriter();
    }

    @Bean
    @StepScope
    @RefreshScope
    public MyFunctionProcessor processor() throws IOException {
        return new MyFunctionProcessor();
    }

    @Bean
    public MyPrationner partitioner() {
        return new MyPrationner();
    }

    @Bean
    public Step masterStep() throws SQLException, IOException, ClassNotFoundException {
        return stepBuilderFactory.get("masterStep")
            .partitioner("MyFunctionStep", partitioner())
            .step(MyFunctionStep())
            .gridSize(gridSize)
            .taskExecutor(MyFunctionTaskExecutor())
            .build();
    }

    @Bean
    public TaskExecutor myFunctionTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setThreadNamePrefix("MyFunctionTaskExecutor_");
        int corePoolSize = gridSize   2;
        int maxPoolSize = corePoolSize * 2;
        taskExecutor.setMaxPoolSize(maxPoolSize);
        taskExecutor.setAllowCoreThreadTimeOut(true);
        taskExecutor.setCorePoolSize(corePoolSize);
        taskExecutor.setQueueCapacity(Integer.MAX_VALUE);
        return taskExecutor;
    }

    @Bean
    public Step myFunctionStep() throws IOException, ClassNotFoundException, SQLException {
        return stepBuilderFactory.get("MyFunctionStep")
            .<MyEntity, MyEntity>chunk(chunckSize)
            .reader(reader)
            .faultTolerant()
            .skipLimit(MAX_NUMBER_CARD)
            .skip(InvalidCardNumberException.class)
            .skip(TokenManagementException.class)
            .processor(processor())
            .listener(new MyEntityProcessListener())
            .writer(writer())
            .listener(new MyEntityWriteListener())
            .build();
    }

    @Bean
    public Job myFunctionJob(@Qualifier("MyFunctionStep") Step myFunctionStep)
        throws SQLException, IOException, ClassNotFoundException {
        if (!batchIsEnabled) {
            LOGGER.error(JOB_DISABLED);
            System.exit(0);
        }
        return jobBuilderFactory.get("MyFunctionJob")
            .listener(new MyFunctionJobListener())
            .incrementer(new RunIdIncrementer())
            .flow(masterStep())
            .end()
            .build();
    }

}

   logging.level.org.hibernate.SQL=DEBUG
   logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
   spring.datasource.type=com.zaxxer.hikari.HikariDataSource
   spring.datasource.pool-name=${spring.application.name}-pool
   spring.datasource.url=jdbc:h2:mem:MYDB;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS MYDB
   spring.datasource.username=sa
   spring.datasource.password=sa
   spring.datasource.driver-class-name=org.h2.Driver
   spring.datasource.database-platform=org.hibernate.dialect.H2Dialect
   spring.jpa.defer-datasource-initialization=true

   #initialize batch schema
   spring.batch.jdbc.initialize-schema=always
   spring.datasource.initialization-mode=always
   spring.sql.init.mode=always
   spring.jpa.hibernate.ddl-auto=none
   #spring.jpa.hibernate.ddl-auto=create
   spring.h2.console.enabled=true
   # Custom H2 Console URL
   spring.h2.console.path=/h2
   spring.jpa.generate-ddl=true
   #jpa.hibernate.ddl-auto=create-drop
   spring.datasource.hikari.pool-name=${spring.application.name}-pool
   spring.datasource.hikari.connection-timeout=20000
   spring.datasource.hikari.maximum-pool-size=30
   spring.datasource.hikari.max-lifetime=86400000
   spring.datasource.hikari.idle-timeout=600000
   spring.datasource.hikari.keepalive-time=30000
   spring.datasource.hikari.minimum-idle=10
   spring.datasource.jmx-enabled=true`

CodePudding user response:

I put creation tables and injection data sql scripts in ReaderConfig with @Sql anotation when I define the reader Bean for test.

It is too late to create tables at that point. You need to initialize the data source with Spring Batch tables and your custom tables before running your job. This can be done on the test setup phase, not the item reader setup phase.

Please check the documentation on how to initialize the data source with Spring Boot.

  • Related