diff --git a/spring-batch-core/.springBeans b/spring-batch-core/.springBeans index 88b2c2284..4f18db94b 100644 --- a/spring-batch-core/.springBeans +++ b/spring-batch-core/.springBeans @@ -21,13 +21,8 @@ src/test/resources/org/springframework/batch/core/configuration/xml/common-context.xml src/test/resources/org/springframework/batch/core/configuration/xml/OneStepJobParserTests-context.xml src/test/resources/org/springframework/batch/core/configuration/xml/TwoStepJobParserTests-context.xml - src/test/resources/org/springframework/batch/core/annotation/batch-component-context.xml src/test/resources/org/springframework/batch/core/scope/util/AsyncPlaceholderTargetSourceTests-context.xml src/test/resources/org/springframework/batch/core/scope/AsyncStepScopeIntegrationTests-context.xml - src/test/resources/org/springframework/batch/core/annotation/batch-component-context-scoped.xml - src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver-nonscanned.xml - src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver.xml - src/test/resources/org/springframework/batch/core/annotation/component-scan-context.xml src/test/resources/org/springframework/batch/core/configuration/xml/DecisionJobParserTests-context.xml src/test/resources/org/springframework/batch/core/configuration/xml/JobExecutionListenerParserTests-context.xml src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BatchComponent.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BatchComponent.java deleted file mode 100644 index d57934f8d..000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BatchComponent.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * - */ -package org.springframework.batch.core.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.batch.core.scope.StepScope; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -/** - * Marker interface for components that wish to participate - * in the batch lifecycle. By default, any class annotated - * with this annotation will also has a scope of 'Step' - * - * @author Lucas Ward - * @since 2.0 - * @see StepScope - * @see Component - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Scope("step") -public @interface BatchComponent { - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BatchComponentScopeMetaDataResolver.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BatchComponentScopeMetaDataResolver.java deleted file mode 100644 index ebfce0059..000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BatchComponentScopeMetaDataResolver.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * - */ -package org.springframework.batch.core.annotation; - -import java.util.Map; - -import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.AnnotationScopeMetadataResolver; -import org.springframework.context.annotation.ScopeMetadata; -import org.springframework.context.annotation.ScopeMetadataResolver; -import org.springframework.context.annotation.ScopedProxyMode; - -/** - * Implementation of the ScopeMetaDataResolver that checks for the {@link BatchComponent} - * annotation on the BeanDefinition passed in, and if found sets the scope to step. The default - * resolver, AnnotationScopeMetadataResolver is used for any classes that don't contain the - * {@link BatchComponent} annotation. - * - * @author Lucas Ward - * @since 2.0 - * @see BeanDefinition - * @see BatchComponent - */ -public class BatchComponentScopeMetaDataResolver implements - ScopeMetadataResolver { - - ScopeMetadataResolver delegate = new AnnotationScopeMetadataResolver(); - - /* - * (non-Javadoc) - * @see org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata(org.springframework.beans.factory.config.BeanDefinition) - */ - public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { - - if(definition instanceof AnnotatedBeanDefinition){ - AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; - Map attributes = - annDef.getMetadata().getAnnotationAttributes(BatchComponent.class.getName()); - if(attributes != null){ - ScopeMetadata metadata = new ScopeMetadata(); - metadata.setScopeName("step"); - metadata.setScopedProxyMode(ScopedProxyMode.INTERFACES); - return metadata; - } - } - - return delegate.resolveScopeMetadata(definition); - } - - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessor.java deleted file mode 100644 index 710332b65..000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessor.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * - */ -package org.springframework.batch.core.annotation; - -import java.lang.reflect.Method; - -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.aop.support.DefaultIntroductionAdvisor; -import org.springframework.aop.support.DelegatingIntroductionInterceptor; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.batch.core.step.AbstractStep; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.AnnotationUtils; - - -/** - * @author Lucas Ward - * - */ -public class StepComponentBeanPostProcessor implements BeanPostProcessor, Ordered { - - private AbstractStep step; - private String basePackage; - - public StepComponentBeanPostProcessor(AbstractStep step, String basePackage) { - this.step = step; - this.basePackage = basePackage; - } - - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - // if it implements the StepExecutionListener interface, we'll register - // it directly as such - - if (bean instanceof StepExecutionListener) { - step.registerStepExecutionListener((StepExecutionListener) bean); - } - - Class clazz = bean.getClass(); - if(bean instanceof FactoryBean){ - clazz = ((FactoryBean)bean).getObjectType(); - } - - // If the class isn't of the correct package, isn't annotated with the - // BatchComponent annotation, we won't put it in. - if (!clazz.getName().startsWith(basePackage) - || AnnotationUtils.findAnnotation(clazz, BatchComponent.class) == null) { - return bean; - } - - ProxyFactory proxyFactory = new ProxyFactory( - new Class[] { StepExecutionListener.class }); - - StepExecutionListenerMixin listenerMixin = new StepExecutionListenerMixin(bean); - - Method[] methods = clazz.getMethods(); - for (Method method : methods) { - if(AnnotationUtils.findAnnotation(method, BeforeStep.class) != null){ - listenerMixin.setBeforeStepMethod(method); - } - - if(AnnotationUtils.findAnnotation(method, AfterStep.class) != null){ - listenerMixin.setAfterStepMethod(method); - } - } - - proxyFactory.addAdvisor(new DefaultIntroductionAdvisor(listenerMixin, StepExecutionListener.class)); - StepExecutionListener listener = (StepExecutionListener)proxyFactory.getProxy(); - step.registerStepExecutionListener(listener); - - return null; - } - - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - - return bean; - } - - private class StepExecutionListenerMixin extends DelegatingIntroductionInterceptor implements StepExecutionListener{ - - Object bean; - Method afterStepMethod; - Method beforeStepMethod; - - public StepExecutionListenerMixin(Object bean) { - this.bean = bean; - } - - public void setBeforeStepMethod(Method beforeStepMethod) { - this.beforeStepMethod = beforeStepMethod; - } - - public void setAfterStepMethod(Method afterStepMethod) { - this.afterStepMethod = afterStepMethod; - } - - public ExitStatus afterStep(StepExecution stepExecution) { - if(afterStepMethod != null){ - invokeMethod(afterStepMethod, bean); - } - return null; - } - - public void beforeStep(StepExecution stepExecution) { - if(beforeStepMethod != null){ - invokeMethod(beforeStepMethod, bean); - } - } - } - - private Object invokeMethod(Method method, Object bean, Object... args){ - - try { - return method.invoke(bean, args); - } catch (Exception e) { - if(e instanceof RuntimeException){ - throw (RuntimeException)e; - } - throw new IllegalArgumentException("Failed to invoke method: [" + method + "]"); - } - } - - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; - } - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/util/MethodInvokerUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/util/MethodInvokerUtils.java index ae9d97ccd..efbf3142f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/util/MethodInvokerUtils.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/util/MethodInvokerUtils.java @@ -36,6 +36,16 @@ import org.springframework.util.ReflectionUtils; */ public class MethodInvokerUtils { + /** + * Create a {@link MethodInvoker} using the provided method name to search. + * + * @param object to be invoked + * @param methodName of the method to be invoked + * @param paramsRequired boolean indicating whether the parameters are required, if false, a no args version of the + * method will be searched for. + * @param paramTypes - parameter types of the method to search for. + * @return MethodInvoker if the method is found, null if it is not. + */ public static MethodInvoker createMethodInvokerByName(Object object, String methodName, boolean paramsRequired, Class... paramTypes){ Assert.notNull(object, "Object to invoke must not be null"); Method method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, paramTypes); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/BatchComponentIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/BatchComponentIntegrationTests.java deleted file mode 100644 index 70a53daab..000000000 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/BatchComponentIntegrationTests.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - */ -package org.springframework.batch.core.annotation; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * @author Lucas Ward - * - */ -public class BatchComponentIntegrationTests { - - @Test - public void testWithoutResolver(){ - ApplicationContext context = new ClassPathXmlApplicationContext("org/springframework/batch/core/annotation/batch-component-context.xml"); - String[] beanNames = context.getBeanNamesForType(TestComponent.class); - //There should be one instance of TextComponent in the Spring Container, because it's annotated with BatchComponent, and the filter - //is setup. However, the beanDefinition, should not have the scope on it, because there is no proxy set. - assertEquals(1, beanNames.length); - ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory)context.getAutowireCapableBeanFactory(); - BeanDefinition beanDef = beanFactory.getBeanDefinition(beanNames[0]); - //Even though BatchComponent is annotated with StepScope, the scope will still be singleton without the resolver. - assertEquals(BeanDefinition.SCOPE_SINGLETON, beanDef.getScope()); - } - - @Test - public void testWithResolver(){ - - ApplicationContext context = new ClassPathXmlApplicationContext("org/springframework/batch/core/annotation/batch-component-context-with-resolver.xml"); - String[] beanNames = context.getBeanNamesForType(TestComponent.class); - //There should be one instance of TextComponent in the Spring Container, because it's annotated with BatchComponent, and the filter - //is setup. However, the beanDefinition, should not have the scope on it, because there is no proxy set. - assertEquals(1, beanNames.length); - ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory)context.getAutowireCapableBeanFactory(); - BeanDefinition beanDef = beanFactory.getBeanDefinition(beanNames[0]); - //Even though BatchComponent is annotated with StepScope, the scope will still be singleton without the resolver. - assertEquals("step", beanDef.getScope()); - } - - @Test - public void testWithResolverNonScanned(){ - - ApplicationContext context = new ClassPathXmlApplicationContext("org/springframework/batch/core/annotation/batch-component-context-with-resolver-nonscanned.xml"); - String[] beanNames = context.getBeanNamesForType(TestComponent.class); - //There should be one instance of TextComponent in the Spring Container, because it's annotated with BatchComponent, and the filter - //is setup. However, the beanDefinition, should not have the scope on it, because there is no proxy set. - assertEquals(1, beanNames.length); - ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory)context.getAutowireCapableBeanFactory(); - BeanDefinition beanDef = beanFactory.getBeanDefinition(beanNames[0]); - //Even though BatchComponent is annotated with StepScope, the scope will still be singleton without the resolver. - assertEquals(BeanDefinition.SCOPE_SINGLETON, beanDef.getScope()); - } - - @Test - public void testWithScopedComponent(){ - ApplicationContext context = new ClassPathXmlApplicationContext("org/springframework/batch/core/annotation/batch-component-context-scoped.xml"); - String[] beanNames = context.getBeanNamesForType(TestScopedComponent.class); - //There should be one instance of TextComponent in the Spring Container, because it's annotated with BatchComponent, and the filter - //is setup. However, the beanDefinition, should not have the scope on it, because there is no proxy set. - assertEquals(1, beanNames.length); - ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory)context.getAutowireCapableBeanFactory(); - BeanDefinition beanDef = beanFactory.getBeanDefinition(beanNames[0]); - //Even though BatchComponent is annotated with StepScope, the scope will still be singleton without the resolver. - assertEquals(BeanDefinition.SCOPE_SINGLETON, beanDef.getScope()); - } -} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/BatchComponentScopeMetaDataResolverTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/BatchComponentScopeMetaDataResolverTests.java deleted file mode 100644 index a80b28d7e..000000000 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/BatchComponentScopeMetaDataResolverTests.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * - */ -package org.springframework.batch.core.annotation; - -import static org.easymock.EasyMock.*; -import static org.junit.Assert.*; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; -import org.springframework.context.annotation.Scope; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.StandardAnnotationMetadata; - -/** - * @author Lucas Ward - * - */ -public class BatchComponentScopeMetaDataResolverTests { - - AnnotatedBeanDefinition annBeanDef; - AnnotationMetadata metaData; - BatchComponentScopeMetaDataResolver resolver = new BatchComponentScopeMetaDataResolver(); - - @Before - public void init(){ - annBeanDef = createMock(AnnotatedBeanDefinition.class); - } - - @Test - public void testNormalCase(){ - expect(annBeanDef.getMetadata()).andReturn(new StandardAnnotationMetadata(StubScopedClass.class)); - expect(annBeanDef.getMetadata()).andReturn(new StandardAnnotationMetadata(StubScopedClass.class)); - replay(annBeanDef); - assertEquals("step",resolver.resolveScopeMetadata(annBeanDef).getScopeName()); - verify(annBeanDef); - } - - @Test - public void testBatchComponent(){ - - expect(annBeanDef.getMetadata()).andReturn(new StandardAnnotationMetadata(TestComponent.class)); - replay(annBeanDef); - assertEquals("step",resolver.resolveScopeMetadata(annBeanDef).getScopeName()); - verify(annBeanDef); - } - - @Scope("step") - private class StubScopedClass{} -} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessorIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessorIntegrationTests.java deleted file mode 100644 index 3b63fb089..000000000 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessorIntegrationTests.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.springframework.batch.core.annotation; - - -import java.util.Date; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.job.SimpleJob; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations={"component-scan-context.xml"}) -public class StepComponentBeanPostProcessorIntegrationTests { - - @Autowired - private SimpleJob job; - - @Autowired - private JobLauncher jobLauncher; - - @Test - public void testListener() throws Exception{ - - jobLauncher.run(job, new JobParametersBuilder().addDate("run.date", new Date()).toJobParameters()); - - // assertTrue(TestComponent.isAfterStepCalled()); - // assertTrue(TestComponent.isBeforeStepCalled()); - } -} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessorTests.java deleted file mode 100644 index 115c20d82..000000000 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/StepComponentBeanPostProcessorTests.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * - */ -package org.springframework.batch.core.annotation; - -import static org.easymock.EasyMock.createMock; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.step.AbstractStep; - -/** - * @author Lucas Ward - * - */ -public class StepComponentBeanPostProcessorTests { - - @BatchComponent - private class TestComponent { - - boolean afterStepCalled = false; - - @AfterStep - public void testMethod() { - afterStepCalled = true; - } - } - - @Test - public void testNormalCase() throws Exception { - AbstractStep step = new StubStep(); - step.setJobRepository(createMock(JobRepository.class)); - StepComponentBeanPostProcessor postProcessor = new StepComponentBeanPostProcessor( - step, "org.springframework.batch.core.annotation"); - TestComponent testComponent = new TestComponent(); - postProcessor.postProcessAfterInitialization(testComponent, - "testComponent"); - step.execute(new StepExecution("teststep", new JobExecution(11L))); - assertTrue(testComponent.afterStepCalled); - } - - private class StubStep extends AbstractStep { - - @Override - protected void doExecute(StepExecution stepExecution) throws Exception { - stepExecution.setExitStatus(ExitStatus.FINISHED); - } - - } -} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/TestComponent.java b/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/TestComponent.java deleted file mode 100644 index 9157550cb..000000000 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/TestComponent.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * - */ -package org.springframework.batch.core.annotation; - -/** - * @author Lucas Ward - * - */ -@BatchComponent -public class TestComponent { - - private static boolean beforeStepCalled = false; - - private static boolean afterStepCalled = false; - - public static boolean isBeforeStepCalled(){ - return beforeStepCalled; - } - - public static boolean isAfterStepCalled(){ - return afterStepCalled; - } - - @BeforeStep - public void beforeStep(){ - beforeStepCalled = true; - } - - @AfterStep - public void afterStep(){ - afterStepCalled = true; - } -} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/TestScopedComponent.java b/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/TestScopedComponent.java deleted file mode 100644 index 1d26988e5..000000000 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/annotation/TestScopedComponent.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.springframework.batch.core.annotation; - -import org.springframework.context.annotation.Scope; - -@Scope("step") -public class TestScopedComponent { - -} diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-scoped.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-scoped.xml deleted file mode 100644 index c513028b2..000000000 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-scoped.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver-nonscanned.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver-nonscanned.xml deleted file mode 100644 index 213d3811a..000000000 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver-nonscanned.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver.xml deleted file mode 100644 index 9b7c02cfc..000000000 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context-with-resolver.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context.xml deleted file mode 100644 index 087e365bb..000000000 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/batch-component-context.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/component-scan-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/component-scan-context.xml deleted file mode 100644 index 113248dda..000000000 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/annotation/component-scan-context.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -