2016-08-15 8 views
0

したがって、Springバッチ3.0.7.RELEASEとSpring 4.3.2.RELEASEで、リスナーが私のItemProcessorクラスで実行されていない問題があります。 @StepScopeレベルでの通常注入は、以下に示すように@Value("#{jobExecutionContext['" + Constants.SECURITY_TOKEN + "']}")で行われます。しかし、beforeProcessまたはbeforeStepで動作していないため、注釈バージョンとインターフェイスバージョンの両方を試しました。私はほぼ100%確信していますが、これはいつか動作していましたが、なぜ停止したのかわかりません。SpringバッチプロセッサがItemProcessorListenerを実行していない

アイデア?私はそれを間違って設定したように見えますか?

AppBatchConfiguration.java

@Configuration 
@EnableBatchProcessing 
@ComponentScan(basePackages = "our.org.base") 
public class AppBatchConfiguration { 

    private final static SimpleLogger LOGGER = SimpleLogger.getInstance(AppBatchConfiguration.class); 

    private final static String OUTPUT_XML_FILE_PATH_PLACEHOLDER = null; 
    private final static String INPUT_XML_FILE_PATH_PLACEHOLDER = null; 

    @Autowired 
    public JobBuilderFactory jobBuilderFactory; 

    @Autowired 
    public StepBuilderFactory stepBuilderFactory; 

    @Bean(name = "cimAppXmlReader") 
    @StepScope 
    public <T> ItemStreamReader<T> appXmlReader(@Value("#{jobParameters[inputXmlFilePath]}") 
    String inputXmlFilePath) { 
     LOGGER.info("Job Parameter => App XML File Path :" + inputXmlFilePath); 
     StaxEventItemReader<T> reader = new StaxEventItemReader<T>(); 
     reader.setResource(new FileSystemResource(inputXmlFilePath)); 
     reader.setUnmarshaller(mecaUnMarshaller()); 
     reader.setFragmentRootElementNames(getAppRootElementNames()); 
     reader.setSaveState(false); 

     // Make the StaxEventItemReader thread-safe 
     SynchronizedItemStreamReader<T> synchronizedItemStreamReader = new SynchronizedItemStreamReader<T>(); 
     synchronizedItemStreamReader.setDelegate(reader); 

     return synchronizedItemStreamReader; 
    } 

    @Bean 
    @StepScope 
    public ItemStreamReader<JAXBElement<AppIBTransactionHeaderType>> appXmlTransactionHeaderReader(@Value("#{jobParameters[inputXmlFilePath]}") 
    String inputXmlFilePath) { 
     LOGGER.info("Job Parameter => App XML File Path for Transaction Header :" + inputXmlFilePath); 
     StaxEventItemReader<JAXBElement<AppIBTransactionHeaderType>> reader = new StaxEventItemReader<>(); 
     reader.setResource(new FileSystemResource(inputXmlFilePath)); 
     reader.setUnmarshaller(mecaUnMarshaller()); 

     String[] fragmentRootElementNames = new String[] {"AppIBTransactionHeader"}; 
     reader.setFragmentRootElementNames(fragmentRootElementNames); 
     reader.setSaveState(false); 

     return reader; 
    } 

    @Bean 
    public Unmarshaller mecaUnMarshaller() { 
     Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); 
     marshaller.setPackagesToScan(ObjectFactory.class.getPackage().getName()); 
     return marshaller; 
    } 

    @Bean 
    public Marshaller uberMarshaller() { 
     Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); 
     marshaller.setClassesToBeBound(ServiceRequestType.class); 
     marshaller.setSupportJaxbElementClass(true); 
     return marshaller; 
    } 

    @Bean(destroyMethod="") // To stop multiple close calls, see: http://stackoverflow.com/a/23089536 
    @StepScope 
    public ResourceAwareItemWriterItemStream<JAXBElement<ServiceRequestType>> writer(@Value("#{jobParameters[outputXmlFilePath]}") 
    String outputXmlFilePath) { 
     SyncStaxEventItemWriter<JAXBElement<ServiceRequestType>> writer = new SyncStaxEventItemWriter<JAXBElement<ServiceRequestType>>(); 

     writer.setResource(new FileSystemResource(outputXmlFilePath)); 
     writer.setMarshaller(uberMarshaller()); 
     writer.setSaveState(false); 
     HashMap<String, String> rootElementAttribs = new HashMap<String, String>(); 
     rootElementAttribs.put("xmlns:ns1", "http://some.org/corporate/message/2010/1"); 
     writer.setRootElementAttributes(rootElementAttribs); 
     writer.setRootTagName("ns1:SetOfServiceRequests"); 

     return writer; 
    } 

    @Bean 
    @StepScope 
    public <T> ItemProcessor<T, JAXBElement<ServiceRequestType>> appNotificationProcessor() { 
     return new AppBatchNotificationItemProcessor<T>(); 
    } 

    @Bean 
    public ItemProcessor<JAXBElement<AppIBTransactionHeaderType>, Boolean> appBatchCreationProcessor() { 
     return new AppBatchCreationItemProcessor(); 
    } 


    public String[] getAppRootElementNames() {   
     //get list of App Transaction Element Names   
     return AppProcessorEnum.getValues();   
    } 

    @Bean 
    public Step AppStep() { 
     // INPUT_XML_FILE_PATH_PLACEHOLDER and OUTPUT_XML_FILE_PATH_PLACEHOLDER will be overridden 
     // by injected jobParameters using late binding (StepScope) 
     return stepBuilderFactory.get("AppStep") 
       .<Object, JAXBElement<ServiceRequestType>> chunk(10) 
       .reader(appXmlReader(INPUT_XML_FILE_PATH_PLACEHOLDER)) 
       .processor(appNotificationProcessor()) 
       .writer(writer(OUTPUT_XML_FILE_PATH_PLACEHOLDER)) 
       .taskExecutor(concurrentTaskExecutor()) 
       .throttleLimit(1) 
       .build(); 

    } 

    @Bean 
    public Step BatchCreationStep() { 
     return stepBuilderFactory.get("BatchCreationStep") 
       .<JAXBElement<AppIBTransactionHeaderType>, Boolean>chunk(1) 
       .reader(appXmlTransactionHeaderReader(INPUT_XML_FILE_PATH_PLACEHOLDER)) 
       .processor(appBatchCreationProcessor()) 
       .taskExecutor(concurrentTaskExecutor()) 
       .throttleLimit(1) 
       .build(); 
    } 

    @Bean 
    public Job AppJob() { 
     return jobBuilderFactory.get("AppJob") 
       .incrementer(new RunIdIncrementer()) 
       .listener(AppJobCompletionNotificationListener()) 
       .flow(AppStep()) 
       .next(BatchCreationStep()) 
       .end() 
       .build(); 
    } 

    @Bean 
    public JobCompletionNotificationListener AppJobCompletionNotificationListener() { 
     return new JobCompletionNotificationListener(); 
    } 

    @Bean 
    public TaskExecutor concurrentTaskExecutor() { 
     SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); 
     taskExecutor.setConcurrencyLimit(1); 
     return taskExecutor; 
    } 
} 

AppBatchNotificationItemProcessor.java

@StepScope 
public class AppBatchNotificationItemProcessor<E> extends AppAbstractItemProcessor<E, JAXBElement<ServiceRequestType>> implements ItemProcessor<E, JAXBElement<ServiceRequestType>>, StepExecutionListener { 

    // This is populated correctly 
    @Value("#{jobExecutionContext['" + Constants.SECURITY_TOKEN + "']}") 
    private SecurityToken securityToken; 

    @Autowired 
    private AppProcessorService processor; 

    @Override 
    public JAXBElement<ServiceRequestType> process(E item) throws BPException { 
     // Do Stuff 
     return srRequest; 
    } 

    @BeforeProcess 
    public void beforeProcess(E item) { 
     System.out.println("Doesn't execute"); 
    } 

    @Override 
    public void beforeStep(StepExecution stepExecution) { 
     // Doesn't execute 
     System.out.println("Doesn't execute"); 
    } 

    @Override 
    public ExitStatus afterStep(StepExecution stepExecution) { 
     // Doesn't execute 
     System.out.println("Doesn't execute"); 
    } 

} 

答えて

1

これは、@Beanメソッドで実装ではなくインターフェイスを返すためです。 IMHOでは、Springでjava構成を使用するときに可能な最も具体的な型を返すべきです。理由は次のとおりです。

XMLで設定する場合は、XML設定でクラスを指定します。これにより、実装がSpringに公開され、クラスが実装しているインタフェースをすべて適切に検出して処理できるようになります。 Java構成を使用する場合は、@Beanメソッドの戻り値の型がその情報の代わりになります。そして問題があります。戻り値の型がインタフェースの場合、Springはその特定のインタフェースのみを認識し、実装が実装できるすべてのインタフェースを認識するわけではありません。できるだけ具体的な型を返すことで、実際に返ってきたことをSpringの洞察力で知らせるので、さまざまな登録と配線の使用例をよりよく扱うことができます。

具体的な例として、ItemProcessorを返すので、ステップスコープ(したがってプロキシ化)しているので、すべてのSpringはItemProcessorインターフェイスで期待されるメソッド/ビヘイビアを知っています。実装(AppBatchNotificationItemProcessor)を返すと、他の動作を自動設定することができます。

+0

マイケルさん、ありがとうございました。 –

0
私が覚えている限りでは、あなたが使用している場合は、ステップ上のリスナーとして直接リーダー、ライター、プロセッサを登録する必要が

ステップスコープ。

StepScopeは、フレームワークがどのような種類のインターフェイスを認識できないようにします。 @annotations(@ @ BeforeProcessなど)では、プロキシが実際に実装/定義しているため、リスナーとして登録することはできません。

だから、私は

return stepBuilderFactory.get("AppStep") 
      .<Object, JAXBElement<ServiceRequestType>> chunk(10) 
      .reader(appXmlReader(INPUT_XML_FILE_PATH_PLACEHOLDER)) 
      .processor(appNotificationProcessor()) 
      .writer(writer(OUTPUT_XML_FILE_PATH_PLACEHOLDER)) 

     .listener(appNotificationProcessor()) 

      .taskExecutor(concurrentTaskExecutor()) 
      .throttleLimit(1) 
      .build(); 

を追加する場合、それは動作しますと仮定します。

関連する問題