2015-02-11 30 views
7

Tôi đang có công việc theo lô xuân độc lập. Này hoạt động hoàn toàn tốt đẹp khi trong JUnitVấn đề phạm vi lô mùa xuân khi sử dụng khởi động mùa xuân

@RunWith(SpringJUnit4ClassRunner.class) 
//@SpringApplicationConfiguration(classes = KPBootApplication.class) 
@ContextConfiguration(locations={"classpath:kp-sb.xml"}) 
public class KPBootApplicationTests { 

    private final static Logger LOG=LoggerFactory.getLogger(KPBootApplicationTests.class); 

    @Autowired 
    ApplicationContext context; 

    @Autowired 
    private JobLauncher jobLauncher; 

    @Autowired 
    private Job job; 

    @Test 
    public void testJob() { 

     final JobParameters jobParameters = new JobParametersBuilder() 
       .toJobParameters(); 

     JobExecution execution; 
     try { 
      execution = jobLauncher.run(job, jobParameters); 
      final ExitStatus status = execution.getExitStatus(); 

      if (ExitStatus.COMPLETED.getExitCode().equals(status.getExitCode())) { 
       LOG.info("Job completed Yeaaaaaaaa!!!!!"); 
      } else { 
       final List<Throwable> exceptions = execution 
         .getAllFailureExceptions(); 
       for (final Throwable throwable : exceptions) { 
        LOG.error(throwable.getMessage(), throwable); 

       } 
      } 
     } catch (JobExecutionAlreadyRunningException e) { 
      LOG.error(e.getMessage(), e); 
     } catch (JobRestartException e) { 
      LOG.error(e.getMessage(), e); 
     } catch (JobInstanceAlreadyCompleteException e) { 
      LOG.error(e.getMessage(), e); 
     } catch (JobParametersInvalidException e) { 
      LOG.error(e.getMessage(), e); 
     } 

    } 

} 

Và các tập tin cấu hình

<!-- Below code till Job Repo is commented out during spring-boot --> 
<context:property-placeholder 
    properties-ref="kpProps" /> 
<util:properties id="kpProps"> 
    <prop key="app.file.path"> 
     D:/temp/kp1/all 
    </prop> 
    <prop key="app.max_thread_num"> 
     10 
    </prop> 
</util:properties> 

<!-- 
<bean id="jobLauncher" 
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
    <property name="jobRepository" ref="jobRepository" /> 
</bean> 

<bean id="jobRepository" 
    class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"> 
    <property name="transactionManager" ref="batchTransactionManager" /> 
</bean> 
--> 

<bean id="batchTransactionManager" 
    class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"> 
    <property name="rollbackOnCommitFailure" value="false" /> 
</bean> 

<bean id="multiResourcePartitionerReq" 
    class="org.springframework.batch.core.partition.support.MultiResourcePartitioner"> 
    <property name="resources" value="file:${app.file.path}/kp_http_request*" /> 
</bean> 

<bean id="multiResourcePartitionerRes" 
    class="org.springframework.batch.core.partition.support.MultiResourcePartitioner"> 
    <property name="resources" value="file:${app.file.path}/kp_http_response*" /> 
</bean> 

<bean id="kpPool" 
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" 
    destroy-method="destroy"> 
    <property name="maxPoolSize" value="${app.max_thread_num}" /> 
</bean> 

<bean id="idIncrementer1" 
    class="org.springframework.batch.core.launch.support.RunIdIncrementer" /> 

<batch:job id="kpGenJob" incrementer="idIncrementer1" 
    job-repository="jobRepository"> 
    <batch:split id="splitStep" next="step4"> 
     <batch:flow> 
      <batch:step id="step2"> 
       <batch:partition partitioner="multiResourcePartitionerReq" 
        step="step2.slave"> 
        <batch:handler task-executor="kpPool" /> 
       </batch:partition> 
      </batch:step> 
     </batch:flow> 
     <batch:flow> 
      <batch:step id="step3"> 
       <batch:partition partitioner="multiResourcePartitionerRes" 
        step="step3.slave"> 
        <batch:handler task-executor="kpPool" /> 
       </batch:partition> 
      </batch:step> 
     </batch:flow> 
    </batch:split> 
    <batch:step id="step4"> 
     <batch:tasklet transaction-manager="batchTransactionManager"> 
      <ref bean="kptasklet" /> 
     </batch:tasklet> 
    </batch:step> 
</batch:job> 

<batch:step id="step2.slave"> 
    <batch:tasklet transaction-manager="batchTransactionManager"> 
     <batch:chunk reader="reqItemReader" writer="cvsFileItemWriter" 
      commit-interval="10000" /> 
    </batch:tasklet> 
</batch:step> 

<batch:step id="step3.slave"> 
    <batch:tasklet transaction-manager="batchTransactionManager"> 
     <batch:chunk reader="resItemReader" writer="cvsFileItemWriter" 
      commit-interval="10000" /> 
    </batch:tasklet> 
</batch:step> 

<bean id="reqItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" 
    scope="step"> 

    <property name="resource" value="#{stepExecutionContext['fileName']}" /> 

    <property name="lineMapper"> 
     <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper"> 
      <!-- split it --> 
      <property name="lineTokenizer"> 
       <bean 
        class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer"> 
        <property name="includedFields" value="5,6,8,10,11"></property> 
        <property name="names" 
         value="f1,f2,f3,f4,f5" /> 
        <property name="strict" value="false" /> 
       </bean> 
      </property> 
      <property name="fieldSetMapper"> 
       <bean 
        class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper"> 
        <property name="prototypeBeanName" value="tblHttpData" /> 
       </bean> 
      </property> 
     </bean> 
    </property> 
    <property name="linesToSkip" value="1"></property> 
</bean> 

<bean id="tblHttpData" class="com.kp.batch.batch.job.domain.TblHttpData" 
    scope="prototype" /> 

<bean id="resItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" 
    scope="step"> 

    <property name="resource" value="#{stepExecutionContext['fileName']}" /> 

    <property name="lineMapper"> 
     <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper"> 
      <!-- split it --> 
      <property name="lineTokenizer"> 
       <bean 
        class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer"> 
        <property name="includedFields" value="3,4"></property> 
        <property name="names" value="f1,f2" /> 
        <property name="strict" value="false" /> 
       </bean> 
      </property> 
      <property name="fieldSetMapper"> 

       <bean 
        class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper"> 
        <property name="prototypeBeanName" value="tblHttpData" /> 
        <property name="strict" value="true" /> 
       </bean> 
      </property> 
     </bean> 
    </property> 
    <property name="linesToSkip" value="1"></property> 
</bean> 

<bean id="kptasklet" class="com.kp.batch.batch.job.step.KPTasklet" /> 

<bean id="cvsFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" 
    scope="step"> 
    <!-- write to this csv file --> 
    <property name="resource" value="#{stepExecutionContext['fileName']}.tmp" /> 
    <property name="shouldDeleteIfExists" value="true" /> 

    <property name="lineAggregator"> 
     <bean 
      class="org.springframework.batch.item.file.transform.DelimitedLineAggregator"> 
      <property name="delimiter" value="," /> 

      <property name="fieldExtractor"> 
       <bean 
        class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor"> 
        <property name="names" 
         value="server,refferer,application,baseApplication,httpSize" /> 
       </bean> 
      </property> 
     </bean> 
    </property> 

</bean> 

The Class Main

@SpringBootApplication 
@EnableBatchProcessing 
@ImportResource(value={"classpath:spring-context.xml"}) 
public class KPBootApplication { 

    private final static Logger LOG = LoggerFactory 
      .getLogger(KPBootApplication.class); 

    public static void main(String[] args) { 
     ApplicationContext ctx = SpringApplication.run(
       KPBootApplication.class, args); 
     LOG.info("Application KPBOOT Started"); 
     SayHello hello = (SayHello) ctx.getBean("sayHello"); 
     if (hello != null) { 
      LOG.debug("hello is not null"); 
      LOG.info("Got message {}", hello.getMessage()); 
     } else { 
      LOG.debug("hello is null"); 
     } 
     LOG.info("Done"); 

    } 
} 

Khi tôi nhận xét ra contextconfiguration chú thích và cho phép lò xo khởi động bằng cách cho phép @SpringApplicationConfiguration (lưu ý: Tôi đã kích hoạt lô mùa xuân bằng cách sử dụng chú thích @EnableBatchProcessing) và nhận xét ra đậu được automcatically tạo ra bởi lò xo khởi động cho hàng loạt mùa xuân như JobRepo tôi nhận được lỗi sau nói không giữ bối cảnh cho phạm vi bước

java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94) 
    at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:252) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:254) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:217) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step2': Cannot resolve reference to bean 'step2.slave' while setting bean property 'step'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step2.slave': Cannot resolve reference to bean 'reqItemReader' while setting bean property 'itemReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reqItemReader': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1469) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:743) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321) 
    at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:98) 
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68) 
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86) 
    ... 25 common frames omitted 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step2.slave': Cannot resolve reference to bean 'reqItemReader' while setting bean property 'itemReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reqItemReader': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1469) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 42 common frames omitted 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reqItemReader': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:352) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 52 common frames omitted 
Caused by: java.lang.IllegalStateException: No context holder available for step scope 
    at org.springframework.batch.core.scope.StepScope.getContext(StepScope.java:160) 
    at org.springframework.batch.core.scope.StepScope.get(StepScope.java:99) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337) 
    ... 54 common frames omitted 

Không chắc chắn tại sao khởi động mùa xuân ném lỗi
LƯU Ý: mùa xuân-khởi động phiên bản 1.2 .1

+0

Có gì trong 'KPBootApplication.class' của bạn? –

+0

@DaveSyer lớp chính của nó –

Trả lời

10

Đây có thể là lỗi (chúng tôi vẫn đang điều tra), tuy nhiên chúng tôi có một công việc xung quanh. Nguyên nhân của việc này là khi sử dụng @EnableBatchProcessing, StepScope được cấu hình tự động giả định cấu hình java và do đó không ủy quyền cho các hạt cà phê có phạm vi bước, khiến chúng được tạo quá sớm. Công việc xung quanh là tự cấu hình một StepScope trong cấu hình XML của bạn với cấu hình sau:

<bean id="stepScope" class="org.springframework.batch.core.scope.StepScope"> 
    <property name="autoProxy" value="true"/> 
</bean> 
+0

Điều đó làm việc hoàn hảo tốt ... cảm ơn rất nhiều .... Tôi có cần phải tạo JIRA không? –

+2

Đã có: https://jira.spring.io/browse/BATCH-2351 –

+2

Một lưu ý quan trọng khác về việc thêm định nghĩa bean Step/JobScope thông qua JavaConfig: nó phải được khai báo trong một classe @Configuration được phân tách (được tải từ thực tế qua @ @ Nhập), hoặc sẽ có vấn đề về chu kỳ – kij

3

bình luận của Michael đang làm việc cho tôi, tôi cũng đang cung cấp JavaConfig copy-paste thay thế cho những người lười biếng như tôi :)

@Bean 
public StepScope stepScope() { 
    final StepScope stepScope = new StepScope(); 
    stepScope.setAutoProxy(true); 
    return stepScope; 
} 
+0

Bạn đã quản lý để khởi tạo StepScope như thế nào? – CKing

+0

Mã này thực sự đang tạo ra cá thể của StepScope. Bạn cần đưa mã này vào bất kỳ lớp @Configuration nào. – Gondy

+0

Vấn đề ở đây là có hai loại 'StepScope' trong bản phân phối' Spring'. Đó là một chú thích và một là một lớp. Tôi đã giả sử bạn đang instantiating 'StepScope' chú thích và do đó sự nhầm lẫn. – CKing

1

Thấy bạn đang sử dụng @RunWith(SpringRunner.class), tuyên bố @TestExecutionListeners({..., StepScopeTestExecutionListener.class}) phía trên lớp học của bạn sẽ thiết lập phạm vi cho bạn.

Tương tự với @TestExecutionListeners({..., JobScopeTestExecutionListener.class}) cho jobScope.

Các vấn đề liên quan