2013-05-15 1 views
5

Я разрабатываю Spring-пакетное задание, которое обрабатывает несколько входных файлов параллельно с помощью MultiResourcePartitioner. В ItemProcessor мне нужно получить количество записей в текущем входном файле. Я получаю имя файла из шага контекста и отсчитать количество строк в файле:Spring Batch: создание контекста в процессоре для секционированного шага

StepSynchronizationManager.register(stepExecution); 
StepContext stepContext = StepSynchronizationManager.getContext(); 
StepSynchronizationManager.close(); 
log.trace("stepContext: " + stepContext.getStepExecution().getExecutionContext().entrySet().toString()); 
... 
UrlResource currentFile = new UrlResource(stepContext.getStepExecution().getExecutionContext().getString("fileName")); 

Все это, кажется, работает, но я получаю исключение при доступе к контексту шага из потоков процессора:

2013-05-15 11:44:35,178 DEBUG [org.springframework.batch.core.step.tasklet.TaskletStep] <taskExecutor-3> - Rollback for RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.processor': 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 
2013-05-15 11:44:35,194 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] <taskExecutor-3> - Returning JDBC Connection to DataSource 
2013-05-15 11:44:35,194 DEBUG [org.springframework.batch.repeat.support.RepeatTemplate] <taskExecutor-3> - Handling exception: org.springframework.beans.factory.BeanCreationException, caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.processor': 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 
2013-05-15 11:44:35,194 DEBUG [org.springframework.batch.repeat.support.RepeatTemplate] <taskExecutor-3> - Handling fatal exception explicitly (rethrowing first of 1): org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.processor': 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 
2013-05-15 11:44:35,210 ERROR [org.springframework.batch.core.step.AbstractStep] <taskExecutor-3> - Encountered an error executing the step 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.processor': 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:341) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192) 
    at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182) 
    at $Proxy14.process(Unknown Source) 
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:125) 
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:291) 
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:190) 
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74) 
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386) 
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130) 
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264) 
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76) 
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367) 
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214) 
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143) 
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250) 
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195) 
    at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:120) 
    at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:118) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:722) 
Caused by: java.lang.IllegalStateException: No context holder available for step scope 
    at org.springframework.batch.core.scope.StepScope.getContext(StepScope.java:197) 
    at org.springframework.batch.core.scope.StepScope.get(StepScope.java:139) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:327) 
    ... 24 more 

Есть ли способ получить текущее имя входного файла от процессора многораздельного задания?

Вот соответствующая конфигурация:

<batch:job id="acct"> 
    <batch:step id="init" parent="abstractStep" next="processStep"> 
     <batch:tasklet ref="fileDeleteTasklet" /> 
    </batch:step> 
    <batch:step id="processStep"> 
     <batch:partition step="processInput" partitioner="partitioner"> 
      <batch:handler grid-size="2" task-executor="taskExecutor" /> 
     </batch:partition> 
    </batch:step> 
</batch:job> 

<batch:step id="processInput"> 
    <batch:tasklet> 
     <batch:chunk reader="reader" processor="processor" writer="writer" commit-interval="3"> 
      <batch:streams> 
       <batch:stream ref="reader"/> 
       <batch:stream ref="flatFileItemWriter"/> 
      </batch:streams> 
     </batch:chunk> 
    </batch:tasklet> 
</batch:step> 

<bean id="partitioner" class="org.springframework.batch.core.partition.support.MultiResourcePartitioner" scope="step"> 
    <property name="keyName" value="fileName"/> 
    <property name="resources" value="file:#{jobParameters['inputFilePattern']}"/> 
</bean> 

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> 
    <property name="corePoolSize" value="5"/> 
    <property name="maxPoolSize" value="5"/> 
</bean> 

<bean id="reader" 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"> 
      <property name="lineTokenizer"> 
       <bean class="org.springframework.batch.item.file.transform.FixedLengthTokenizer"> 
        <property name="names" value="recordType,reserved,aCode,bCode,acctNumber,idType,cCode" /> 
        <property name="columns" value="1,2,3-6,7-9,10-15,16,17-19" /> 
        <property name="strict" value="false" /> 
       </bean> 
      </property> 
      <property name="fieldSetMapper"> 
       <bean class="com.example.batch.acct.AcctInputFieldSetMapper" /> 
      </property> 
     </bean> 
    </property> 
</bean> 

<bean id="processor" class="com.example.batch.acct.AcctProcessor" scope="step"> 
    <property name="soapClient" ref="soapClient" /> 
    <property name="maxNumIds" value="${batch.soap.numberOfIds}" /> 
    <aop:scoped-proxy /> 
</bean> 
+0

какая версия весенней и весенней партии вы используете? – Cygnusx1

+0

Я использую Spring 3.0.6 и Spring Batch 2.1.9. – iguanodon

ответ

1

Ответил на Spring Batch forum:

Интерфейс ItemProcessor не раскрывает способ доступа к StepContext, так что вам нужно, чтобы ввести его самостоятельно:

<bean id="itemProcessor" class="com.myApp.MyItemProcessor" scope="step"> 
    <property name="stepContext" value="#{stepExecutionContext}"/> 
</bean> 

Предполагая, что ваш профессионал класс cessor имеет открытое свойство: stepContext.

- Michael Minella, Spring Batch Lead

+1

Возможно, вы захотите принять свой ответ. Прочтите http://stackoverflow.com/help/self-answer – falsarella

0
<bean id="itemProcessor" class="com.myApp.MyItemProcessor" scope="step"> 
    <property name="stepContext" value="#{stepExecutionContext}"/> 
</bean> 

В этом случае, когда stepContex является типом org.springframework.batch.core.scope.context.StepContext, как предполагает название этого свойства, я получаю исключение:

орг .springframework.beans.factory.BeanCreationException: Ошибка создание bean-компонента с именем 'sco pedTarget.itemProcessor ', определенный в ресурс пути класса [META-INF/jobs/Job.xml]: Инициализация компонента не выполнена; вложенное исключение org.springframework.beans.ConversionNotSupportedException: Не удалось новообращенного значение свойства типа «java.util.Collections $ UnmodifiableMap» до требуемого типа «org.springframework.batch.core.scope.context.StepContext» для property 'stepContext'; вложенное исключение java.lang.IllegalStateException: Невозможно преобразовать значение типа «java.util.Collections $ UnmodifiableMap» для требуемого типа «org.springframework.batch.core.scope.context.StepContext» для собственности «stepContext» : нет соответствия редакторов или преобразование стратегии найдено

Я не нужен доступ к jobExecutionId внутри ItemProcessor, поэтому я изменил эту конфигурацию:

<bean id="itemProcessor" class="com.myApp.MyItemProcessor" scope="step"> 
    <property name="stepExecution" value="#{stepExecution}"/> 
</bean> 

собственности "stepExecution" представляет собой тип org.springframework.batch.core.StepExecution