Spring Batch JpaPagingItemReader не имеет EntityManager в тестах (NPE) - PullRequest
0 голосов
/ 12 июня 2019

У меня есть небольшое задание Spring Batch с использованием JpaPagingItemReader.Работа хорошо работает, когда я запускаю из командной строки, но когда я хочу проверить @StepScope компонент JpaPagingItemReader, я получаю NullPointerException.Я не понимаю, почему работа работает хорошо, но я не могу проверить это согласно документации.

У меня есть только один простой Employee класс с базовыми JPA аннотациями.

Вот мой класс конфигурации работы:

@Slf4j
@Configuration
@EnableBatchProcessing
public class PaySalaryJobConfiguration {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Autowired
    public PaySalaryJobConfiguration(
            JobBuilderFactory jobBuilderFactory,
            StepBuilderFactory stepBuilderFactory
    ) {
        this.jobBuilderFactory = jobBuilderFactory;
        this.stepBuilderFactory = stepBuilderFactory;
    }

    @Bean
    @StepScope
    public ItemProcessor<Employee, Employee> employeeProcessor() {
        return item -> {
            log.info("Process item: {}", item);
            return item;
        };
    }

    @Bean
    @StepScope
    public JpaPagingItemReader<Employee> someoneReader(
            EntityManagerFactory entityManagerFactory
    ) {
        return new JpaPagingItemReaderBuilder<Employee>()
                .name("someone-reader")
                .entityManagerFactory(entityManagerFactory)
                .queryString("Select e from Employee e order by e.id asc")
                .pageSize(1)
                .build();
    }

    @Bean
    @StepScope
    public FlatFileItemWriter<Employee> csvWriter(
            @Value("#{jobParameters['output.path.csv']}") String outputPath
    ) {
        DelimitedLineAggregator<Employee> lineAggregator = new DelimitedLineAggregator<>();
        lineAggregator.setDelimiter(",");

        BeanWrapperFieldExtractor<Employee> fieldExtractor = new BeanWrapperFieldExtractor<>();
        fieldExtractor.setNames(new String[]{"id", "firstName", "lastName", "salary"});
        lineAggregator.setFieldExtractor(fieldExtractor);

        return new FlatFileItemWriterBuilder<Employee>()
                .name("csv-salary-writer")
                .resource(new FileSystemResource(outputPath))
                .lineAggregator(lineAggregator)
                .encoding("UTF-8")
                .build();
    }

    @Bean
    public Step writeSalarySlipToCsv (
            JpaPagingItemReader<Employee> someoneReader,
            FlatFileItemWriter<Employee> csvWriter
    ) {
        return stepBuilderFactory
                .get("retrieve-salary-slip-step")
                .<Employee, Employee>chunk(1)
                .reader(someoneReader)
                .processor(employeeProcessor())
                .writer(csvWriter)
                .stream(someoneReader)
                .build();
    }

    @Bean
    public Job paySalaryJob(
            Step writeSalarySlipToCsv
    ) {
        return jobBuilderFactory
                .get("pay-salary-job")
                .incrementer(new RunIdIncrementer())
                .start(writeSalarySlipToCsv)
                .build();
    }
}

А вот мой тестовый класс:

@Slf4j
@SpringBatchTest
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
@ContextConfiguration(classes = PaySalaryJobConfiguration.class)
public class StepScopeIntegrationTest {

    @Autowired
    private JpaPagingItemReader<Employee> someoneReader;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Before
    public void setUp() {
        log.info("Before execution we have {} entries", jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class ));
    }

    public StepExecution getStepExecution() {
        log.info("Step Execution !");
        StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution("retrieve-salary-slip-step", 1564L);
        log.info("Context = {} / Step = {} ", stepExecution.getExecutionContext(), stepExecution.getStepName());
        return stepExecution;
    }

    @Test
    public void testReader() throws Exception {
        log.info("Page = {}", someoneReader.getPage());
        log.info("PageSize = {}", someoneReader.getPageSize());
        Assert.assertNotNull(someoneReader.read());
    }
}

Проблема возникает в классе JpaPagingItemReader в строке 192:

@Override
@SuppressWarnings("unchecked")
protected void doReadPage() {

    EntityTransaction tx = null;

    if (transacted) {
        tx = entityManager.getTransaction(); // EntityManager is null...
        tx.begin();

        entityManager.flush();
        entityManager.clear();
    }//end if

А вот трассировка стека от выполнения теста:

2019-06-12 17: 17: 32.845 - INFO - [main] {bgtStepScopeIntegrationTest 45} -> Шаг выполнения!2019-06-12 17: 17: 32.845 - INFO - [main] {bgtStepScopeIntegrationTest 47} -> Context = {} / Step = retrieve-salary-slip-step 2019-06-12 17: 17: 32.970 - INFO -[main] {bgtStepScopeIntegrationTest 41} -> перед выполнением у нас есть 4 записи 2019-06-12 17: 17: 33.002 - INFO - [main] {bgtStepScopeIntegrationTest 53} -> страница = 0 2019-06-12 17:17: 33.002 - INFO - [main] {bgtStepScopeIntegrationTest 54} -> PageSize = 1

java.lang.NullPointerException в org.springframework.batch.item.database.JpaPagingItemReader.doReadPage (JpaPjjjReReader )19по адресу org.springframework.batch.item.database.AbstractPagingItemReader.doRead (AbstractPagingItemReader.java:108) по адресу org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read (AbstractItemCountingIm.tram.tj.them.jpg).support.AbstractItemCountingItemStreamItemReader $$ FastClassBySpringCGLIB $$ ebb633d0.invoke () в org.springframework.cglib.proxy.MethodProxy.invoke (MethodProxy.java:204) в org.springframework.aop.framework.CglibAopProxy $ CglibMethodInvocation.invokeJoinpoint (CglibAopProxy.java:746) в org.springframework.aop.framework.joc.springframework.aop.support..java: 185) по адресу org.springframework.aop.framework.CglibAopProxy $ DynamicAdvisedInterceptor.intercept (CglibAopProxy.java:688) по адресу org.springframework.batch.item.database.JpaPagingItemReader $$.groups.test.StepScopeIntegrationTest.testReader (StepScopeIntegrationTest.java:55) в sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) в sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) в java.lang.reflect.Method.invoke (Method.javarmo.un.jpg): at).FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:50) в org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:12) в org.junit.runners.model.Frameworklykelohololo::47) в org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java:17) в org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate (RunBeforebackback) или исполняемый файл (RunBefore).test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate (RunAfterTestExecutionCallbacks.java:83) в org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java:26) в org.springt4.statements.RunBeforeTestMethodCallbacks.evaluate (RunBeforeTestMethodCallbacks.java:75) вorg.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate (RunAfterTestMethodCallbacks.java:86) в org.springframework.test.context.junit4.statements.SpringRepeat.evaluate (SpringRepeat.java:84) в org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:325) в org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild (SpringJUnit4ClassRunner.java:251) в org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild (SpringJUnit4ClassRunner.java:97) в org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:290) в org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:71) в org.junit.runners.ParentRunner.runChildren (ParentRunner.java:288) в org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:58) в org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:268) в org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate (RunBeforeTestClassCallbacks.java:61) в org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate (RunAfterTestClassCallbacks.java:70) в org.junit.runners.ParentRunner.run (ParentRunner.java:363) в org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run (SpringJUnit4ClassRunner.java:190) в org.junit.runner.JUnitCore.run (JUnitCore.java:137) в com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs (JUnit4IdeaTestRunner.java:68) в com.intellij.rt.execution.junit.IdeaTestRunner $ Repeater.startRunnerWithArgs (IdeaTestRunner.java:47) в com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart (JUnitStarter.java:242) в com.intellij.rt.execution.junit.JUnitStarter.main (JUnitStarter.java:70)

Я использую базу данных h2 и заполняю базу данных данными при запуске, предоставляемыми сценариями import.sql и schema-h2.sql. Я работаю с Spring-Boot 2.0.5.RELEASE и Spring Batch Core 4.1.2.RELEASE.

1 Ответ

0 голосов
/ 14 июня 2019

Как сообщил Махмуд Бен Хассин в комментариях, я изменил свой тестовый класс на:

@Slf4j
//@SpringBootTest
@SpringBatchTest
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
@ContextConfiguration(classes = {
        PaySalaryJobConfiguration.class
})
@ActiveProfiles("test")
public class StepScopeIntegrationTest {

    @Autowired
    private JpaPagingItemReader<Employee> someoneReader;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    private StepExecution stepExecution;

    @Before
    public void setUp() {
        log.info("Before execution we have {} entries", jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class ));
    }

    public StepExecution getStepExecution() {
        log.info("Step Execution !");
        stepExecution = MetaDataInstanceFactory.createStepExecution();
        log.info("Context = {} / Step = {} ", stepExecution.getExecutionContext(), stepExecution.getStepName());
        return stepExecution;
    }

    @Test
    public void testReader() throws Exception {
        log.info("Page = {}", someoneReader.getPage());
        log.info("PageSize = {}", someoneReader.getPageSize());
        someoneReader.open(stepExecution.getExecutionContext());
        Assert.assertNotNull(someoneReader.read());
    }
}

И тест теперь работает хорошо.

...