2013-05-15 16 views
5

Sto sviluppando un processo Spring Batch che elabora più file di input in parallelo utilizzando MultiResourcePartitioner. Nel ItemProcessor ho bisogno di ottenere il numero di record nel file di input corrente. Ottengo il nome del file corrente dal contesto passo e leggere il numero di righe nel file:Spring Batch: acquisizione del contesto del passaggio nel processore per il passo partizionato

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")); 

Tutto questo sembra funzionare, ma sto ottenendo eccezioni quando si accede al contesto passo dai fili del processore:

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 

C'è un modo per ottenere il nome del file di input corrente dal processore di un lavoro partizionato?

Qui è il config rilevante:

<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

quale versione di Spring e Spring Batch stai usando? – Cygnusx1

+0

Sto usando Spring 3.0.6 e Spring Batch 2.1.9. – iguanodon

risposta

1

rispose al Spring Batch forum:

L'interfaccia ItemProcessor non espone un modo per accedere alla StepContext, quindi è necessario iniettare da soli:

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

Supponendo che il tuo pro classe cessor ha una proprietà esposta denominata stepContext.

- Michael Minella, Spring Batch Lead

+1

Puoi accettare la tua risposta. Leggi http://stackoverflow.com/help/self-answer – falsarella

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

In questo caso, quando stepContex è un tipo di org.springframework.batch.core.scope.context.StepContext, eccezioni come suggerisce il nome della struttura, che sto ottenendo:

org .springframework.beans.factory.BeanCreationException: Errore creazione di bean con nome 'sco pedTarget.itemProcessor 'definito nella risorsa del percorso di classe [META-INF/jobs/Job.xml]: Inizializzazione del bean non riuscita; l'eccezione annidata è org.springframework.beans.ConversionNotSupportedException: Impossibile convertito valore della proprietà di tipo 'java.util.Collections $ UnmodifiableMap' al tipo richiesto 'org.springframework.batch.core.scope.context.StepContext' per proprietà 'stepContext'; l'eccezione annidata è java.lang.IllegalStateException: Non è possibile convertire il valore di tipo 'java.util.Collections $ UnmodifiableMap' al tipo richiesto 'org.springframework.batch.core.scope.context.StepContext' per proprietà 'stepContext' : nessuna strategia redattori corrispondenti o conversione trovato

avevo bisogno di accedere all'interno jobExecutionIdItemProcessor, così ho cambiato questa configurazione:

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

Proprietà "stepExecution" è un tipo org.springframework.batch.core.StepExecution

Problemi correlati