001/* 002 * Copyright 2013 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.springframework.batch.core.jsr.partition.support; 017 018import org.springframework.batch.core.jsr.configuration.xml.StepFactoryBean; 019import org.springframework.batch.core.jsr.partition.JsrPartitionHandler; 020import org.springframework.beans.BeansException; 021import org.springframework.beans.PropertyValue; 022import org.springframework.beans.factory.config.BeanDefinition; 023import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 024import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 025import org.springframework.beans.factory.config.RuntimeBeanReference; 026 027import javax.batch.api.partition.PartitionAnalyzer; 028import javax.batch.api.partition.PartitionMapper; 029import javax.batch.api.partition.PartitionReducer; 030 031/** 032 * In order for property resolution to occur correctly within the scope of a JSR-352 033 * batch job, initialization of job level artifacts must occur on the same thread that 034 * the job is executing. To allow this to occur, {@link PartitionMapper}, 035 * {@link PartitionReducer}, and {@link PartitionAnalyzer} are all configured to 036 * lazy initialization (equivalent to lazy-init="true"). 037 * 038 * @author Michael Minella 039 * @since 3.0 040 */ 041public class JsrBeanScopeBeanFactoryPostProcessor implements BeanFactoryPostProcessor { 042 043 private JobLevelBeanLazyInitializer initializer; 044 045 /* (non-Javadoc) 046 * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory) 047 */ 048 @Override 049 public void postProcessBeanFactory( 050 ConfigurableListableBeanFactory beanFactory) throws BeansException { 051 if (initializer == null) { 052 this.initializer = new JobLevelBeanLazyInitializer(beanFactory); 053 } 054 055 String[] beanNames = beanFactory.getBeanDefinitionNames(); 056 057 for (String curName : beanNames) { 058 initializer.visitBeanDefinition(beanFactory.getBeanDefinition(curName)); 059 } 060 } 061 062 /** 063 * Looks for beans that may have dependencies that need to be lazily initialized and 064 * configures the corresponding {@link BeanDefinition} accordingly. 065 * 066 * @author Michael Minella 067 * @since 3.0 068 */ 069 public static class JobLevelBeanLazyInitializer { 070 071 private ConfigurableListableBeanFactory beanFactory; 072 073 public JobLevelBeanLazyInitializer(ConfigurableListableBeanFactory beanFactory) { 074 this.beanFactory = beanFactory; 075 } 076 077 public void visitBeanDefinition(BeanDefinition beanDefinition) { 078 String beanClassName = beanDefinition.getBeanClassName(); 079 080 if(StepFactoryBean.class.getName().equals(beanClassName)) { 081 PropertyValue [] values = beanDefinition.getPropertyValues().getPropertyValues(); 082 for (PropertyValue propertyValue : values) { 083 if(propertyValue.getName().equalsIgnoreCase("partitionReducer")) { 084 RuntimeBeanReference ref = (RuntimeBeanReference) propertyValue.getValue(); 085 beanFactory.getBeanDefinition(ref.getBeanName()).setLazyInit(true); 086 } 087 } 088 } 089 090 if(JsrPartitionHandler.class.getName().equals(beanClassName)) { 091 PropertyValue [] values = beanDefinition.getPropertyValues().getPropertyValues(); 092 for (PropertyValue propertyValue : values) { 093 String propertyName = propertyValue.getName(); 094 if(propertyName.equalsIgnoreCase("partitionMapper") || propertyName.equalsIgnoreCase("partitionAnalyzer")) { 095 RuntimeBeanReference ref = (RuntimeBeanReference) propertyValue.getValue(); 096 beanFactory.getBeanDefinition(ref.getBeanName()).setLazyInit(true); 097 } 098 } 099 } 100 } 101 } 102}