, InjectionMetadata> injectionMetadataCache =
- new ConcurrentHashMap<>(64);
-
-
- /**
- * Create a new AutowiredAnnotationBeanPostProcessor
- * for Spring's standard {@link org.springframework.beans.factory.annotation.Autowired} annotation.
- * Also supports JSR-330's {@link jakarta.inject.Inject} annotation, if available.
- */
- @SuppressWarnings("unchecked")
- public SpringAutowiredAnnotationBeanPostProcessor() {
- this.autowiredAnnotationTypes.add(Autowired.class);
- this.autowiredAnnotationTypes.add(Value.class);
- ClassLoader cl = SpringAutowiredAnnotationBeanPostProcessor.class.getClassLoader();
- try {
- this.autowiredAnnotationTypes.add((Class extends Annotation>) cl.loadClass("jakarta.inject.Inject"));
- logger.info("JSR-330 'jakarta.inject.Inject' annotation found and supported for autowiring");
- }
- catch (ClassNotFoundException ex) {
- // JSR-330 API not available - simply skip.
- }
- }
-
-
- /**
- * Set the 'autowired' annotation type, to be used on constructors, fields,
- * setter methods and arbitrary config methods.
- *
The default autowired annotation type is the Spring-provided
- * {@link Autowired} annotation, as well as {@link Value}.
- *
This setter property exists so that developers can provide their own
- * (non-Spring-specific) annotation type to indicate that a member is
- * supposed to be autowired.
- *
- * @param autowiredAnnotationType type to be used by constructors, fields and methods.
- */
- public void setAutowiredAnnotationType(Class extends Annotation> autowiredAnnotationType) {
- Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
- this.autowiredAnnotationTypes.clear();
- this.autowiredAnnotationTypes.add(autowiredAnnotationType);
- }
-
- /**
- * Set the 'autowired' annotation types, to be used on constructors, fields,
- * setter methods and arbitrary config methods.
- *
The default autowired annotation type is the Spring-provided
- * {@link Autowired} annotation, as well as {@link Value}.
- *
This setter property exists so that developers can provide their own
- * (non-Spring-specific) annotation types to indicate that a member is
- * supposed to be autowired.
-
- * @param autowiredAnnotationTypes set of types to be used by constructors, fields and methods.
- */
- public void setAutowiredAnnotationTypes(Set> autowiredAnnotationTypes) {
- Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
- this.autowiredAnnotationTypes.clear();
- this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
- }
-
- /**
- * Set the name of a parameter of the annotation that specifies
- * whether it is required.
- *
- * @param requiredParameterName the name of the parameter.
- *
- * @see #setRequiredParameterValue(boolean)
- */
- public void setRequiredParameterName(String requiredParameterName) {
- this.requiredParameterName = requiredParameterName;
- }
-
- /**
- * Set the boolean value that marks a dependency as required
- * For example if using 'required=true' (the default),
- * this value should be true; but if using
- * 'optional=false', this value should be false.
- *
- * @param requiredParameterValue true if dependency is required.
- *
- * @see #setRequiredParameterName(String)
- */
- public void setRequiredParameterValue(boolean requiredParameterValue) {
- this.requiredParameterValue = requiredParameterValue;
- }
-
- public void setOrder(int order) {
- this.order = order;
- }
-
- @Override
- public int getOrder() {
- return this.order;
- }
-
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
- throw new IllegalArgumentException(
- "AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
- }
- this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
- }
-
-
- @Override
- public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
- if (beanType != null) {
- InjectionMetadata metadata = findAutowiringMetadata(beanType);
- metadata.checkConfigMembers(beanDefinition);
- }
- }
-
- @Override
- public Constructor>[] determineCandidateConstructors(Class> beanClass, String beanName) throws BeansException {
- // Quick check on the concurrent map first, with minimal locking.
- Constructor>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
- if (candidateConstructors == null) {
- synchronized (this.candidateConstructorsCache) {
- candidateConstructors = this.candidateConstructorsCache.get(beanClass);
- if (candidateConstructors == null) {
- Constructor>[] rawCandidates = beanClass.getDeclaredConstructors();
- List> candidates = new ArrayList<>(rawCandidates.length);
- Constructor> requiredConstructor = null;
- Constructor> defaultConstructor = null;
- for (Constructor> candidate : rawCandidates) {
- Annotation annotation = findAutowiredAnnotation(candidate);
- if (annotation != null) {
- if (requiredConstructor != null) {
- throw new BeanCreationException("Invalid autowire-marked constructor: " + candidate +
- ". Found another constructor with 'required' Autowired annotation: " +
- requiredConstructor);
- }
- if (candidate.getParameterTypes().length == 0) {
- throw new IllegalStateException(
- "Autowired annotation requires at least one argument: " + candidate);
- }
- boolean required = determineRequiredStatus(annotation);
- if (required) {
- if (!candidates.isEmpty()) {
- throw new BeanCreationException(
- "Invalid autowire-marked constructors: " + candidates +
- ". Found another constructor with 'required' Autowired annotation: " +
- requiredConstructor);
- }
- requiredConstructor = candidate;
- }
- candidates.add(candidate);
- }
- else if (candidate.getParameterTypes().length == 0) {
- defaultConstructor = candidate;
- }
- }
- if (!candidates.isEmpty()) {
- // Add default constructor to list of optional constructors, as fallback.
- if (requiredConstructor == null && defaultConstructor != null) {
- candidates.add(defaultConstructor);
- }
- candidateConstructors = candidates.toArray(new Constructor>[candidates.size()]);
- }
- else {
- candidateConstructors = new Constructor>[0];
- }
- this.candidateConstructorsCache.put(beanClass, candidateConstructors);
- }
- }
- }
- return (candidateConstructors.length > 0 ? candidateConstructors : null);
- }
-
- @Override
- public PropertyValues postProcessProperties(
- PropertyValues pvs, Object bean, String beanName) throws BeansException {
-
- InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
- try {
- metadata.inject(bean, beanName, pvs);
- }
- catch (Throwable ex) {
- throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
- }
- return pvs;
- }
-
- /**
- * 'Native' processing method for direct calls with an arbitrary target instance,
- * resolving all of its fields and methods which are annotated with @Autowired.
- * @param bean the target instance to process
- * @throws BeansException if autowiring failed
- */
- public void processInjection(Object bean) throws BeansException {
- Class> clazz = bean.getClass();
- InjectionMetadata metadata = findAutowiringMetadata(clazz);
- try {
- metadata.inject(bean, null, null);
- }
- catch (Throwable ex) {
- throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);
- }
- }
-
-
- protected InjectionMetadata findAutowiringMetadata(Class> clazz) {
- // Quick check on the concurrent map first, with minimal locking.
- InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
- if (metadata == null) {
- synchronized (this.injectionMetadataCache) {
- metadata = this.injectionMetadataCache.get(clazz);
- if (metadata == null) {
- metadata = buildAutowiringMetadata(clazz);
- this.injectionMetadataCache.put(clazz, metadata);
- }
- }
- }
- return metadata;
- }
-
- protected InjectionMetadata buildAutowiringMetadata(Class> clazz) {
- LinkedList elements = new LinkedList<>();
- Class> targetClass = clazz;
-
- do {
- LinkedList currElements = new LinkedList<>();
- for (Field field : targetClass.getDeclaredFields()) {
- Annotation annotation = findAutowiredAnnotation(field);
- if (annotation != null) {
- if (Modifier.isStatic(field.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("Autowired annotation is not supported on static fields: " + field);
- }
- continue;
- }
- boolean required = determineRequiredStatus(annotation);
- currElements.add(new AutowiredFieldElement(field, required));
- }
- }
- for (Method method : targetClass.getDeclaredMethods()) {
- Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
- Annotation annotation = BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod) ?
- findAutowiredAnnotation(bridgedMethod) : findAutowiredAnnotation(method);
- if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
- if (Modifier.isStatic(method.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("Autowired annotation is not supported on static methods: " + method);
- }
- continue;
- }
- if (method.getParameterTypes().length == 0) {
- if (logger.isWarnEnabled()) {
- logger.warn("Autowired annotation should be used on methods with actual parameters: " + method);
- }
- }
- boolean required = determineRequiredStatus(annotation);
- PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
- currElements.add(new AutowiredMethodElement(method, required, pd));
- }
- }
- elements.addAll(0, currElements);
- targetClass = targetClass.getSuperclass();
- }
- while (targetClass != null && targetClass != Object.class);
-
- return new InjectionMetadata(clazz, elements);
- }
-
- protected Annotation findAutowiredAnnotation(AccessibleObject ao) {
- for (Class extends Annotation> type : this.autowiredAnnotationTypes) {
- Annotation annotation = AnnotationUtils.getAnnotation(ao, type);
- if (annotation != null) {
- return annotation;
- }
- }
- return null;
- }
-
- /**
- * Obtain all beans of the given type as autowire candidates.
- *
- * @param type the type of the bean.
- * @param the type of the bean.
- * @return the target beans, or an empty Collection if no bean of this type is found
- *
- * @throws BeansException if bean retrieval failed
- */
- protected Map findAutowireCandidates(Class type) throws BeansException {
- if (this.beanFactory == null) {
- throw new IllegalStateException("No BeanFactory configured - " +
- "override the getBeanOfType method or specify the 'beanFactory' property");
- }
- return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type);
- }
-
- /**
- * Determine if the annotated field or method requires its dependency.
- * A 'required' dependency means that autowiring should fail when no beans
- * are found. Otherwise, the autowiring process will simply bypass the field
- * or method when no beans are found.
- * @param annotation the Autowired annotation
- * @return whether the annotation indicates that a dependency is required
- */
- protected boolean determineRequiredStatus(Annotation annotation) {
- try {
- Method method = ReflectionUtils.findMethod(annotation.annotationType(), this.requiredParameterName);
- if (method == null) {
- // annotations like @Inject and @Value don't have a method (attribute) named "required"
- // -> default to required status
- return true;
- }
- return (this.requiredParameterValue == (Boolean) ReflectionUtils.invokeMethod(method, annotation));
- }
- catch (Exception ex) {
- // an exception was thrown during reflective invocation of the required attribute
- // -> default to required status
- return true;
- }
- }
-
- /**
- * Register the specified bean as dependent on the autowired beans.
- */
- private void registerDependentBeans(String beanName, Set autowiredBeanNames) {
- if (beanName != null) {
- for (String autowiredBeanName : autowiredBeanNames) {
- if (this.beanFactory.containsBean(autowiredBeanName)) {
- this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Autowiring by type from bean name '" + beanName +
- "' to bean named '" + autowiredBeanName + "'");
- }
- }
- }
- }
-
- /**
- * Resolve the specified cached method argument or field value.
- */
- private Object resolvedCachedArgument(String beanName, Object cachedArgument) {
- if (cachedArgument instanceof DependencyDescriptor) {
- DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
- TypeConverter typeConverter = this.beanFactory.getTypeConverter();
- return this.beanFactory.resolveDependency(descriptor, beanName, null, typeConverter);
- }
- else if (cachedArgument instanceof RuntimeBeanReference) {
- return this.beanFactory.getBean(((RuntimeBeanReference) cachedArgument).getBeanName());
- }
- else {
- return cachedArgument;
- }
- }
-
-
- /**
- * Class representing injection information about an annotated field.
- */
- private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
-
- private final boolean required;
-
- private volatile boolean cached = false;
-
- private volatile Object cachedFieldValue;
-
- public AutowiredFieldElement(Field field, boolean required) {
- super(field, null);
- this.required = required;
- }
-
- @Override
- protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
- Field field = (Field) this.member;
- try {
- Object value;
- if (this.cached) {
- value = resolvedCachedArgument(beanName, this.cachedFieldValue);
- }
- else {
- DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required);
- Set autowiredBeanNames = new LinkedHashSet<>(1);
- TypeConverter typeConverter = beanFactory.getTypeConverter();
- value = beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
- synchronized (this) {
- if (!this.cached) {
- if (value != null || this.required) {
- this.cachedFieldValue = descriptor;
- registerDependentBeans(beanName, autowiredBeanNames);
- if (autowiredBeanNames.size() == 1) {
- String autowiredBeanName = autowiredBeanNames.iterator().next();
- if (beanFactory.containsBean(autowiredBeanName)) {
- if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
- this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
- }
- }
- }
- }
- else {
- this.cachedFieldValue = null;
- }
- this.cached = true;
- }
- }
- }
- if (value != null) {
- ReflectionUtils.makeAccessible(field);
- field.set(bean, value);
- }
- }
- catch (Throwable ex) {
- throw new BeanCreationException("Could not autowire field: " + field, ex);
- }
- }
- }
-
-
- /**
- * Class representing injection information about an annotated method.
- */
- private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
-
- private final boolean required;
-
- private volatile boolean cached = false;
-
- private volatile Object[] cachedMethodArguments;
-
- public AutowiredMethodElement(Method method, boolean required, PropertyDescriptor pd) {
- super(method, pd);
- this.required = required;
- }
-
- @Override
- protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
- if (checkPropertySkipping(pvs)) {
- return;
- }
- Method method = (Method) this.member;
- try {
- Object[] arguments;
- if (this.cached) {
- // Shortcut for avoiding synchronization...
- arguments = resolveCachedArguments(beanName);
- }
- else {
- Class>[] paramTypes = method.getParameterTypes();
- arguments = new Object[paramTypes.length];
- DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
- Set autowiredBeanNames = new LinkedHashSet<>(paramTypes.length);
- TypeConverter typeConverter = beanFactory.getTypeConverter();
- for (int i = 0; i < arguments.length; i++) {
- MethodParameter methodParam = new MethodParameter(method, i).withContainingClass(bean.getClass());
- descriptors[i] = new DependencyDescriptor(methodParam, this.required);
- arguments[i] = beanFactory.resolveDependency(
- descriptors[i], beanName, autowiredBeanNames, typeConverter);
- if (arguments[i] == null && !this.required) {
- arguments = null;
- break;
- }
- }
- synchronized (this) {
- if (!this.cached) {
- if (arguments != null) {
- this.cachedMethodArguments = new Object[arguments.length];
- for (int i = 0; i < arguments.length; i++) {
- this.cachedMethodArguments[i] = descriptors[i];
- }
- registerDependentBeans(beanName, autowiredBeanNames);
- if (autowiredBeanNames.size() == paramTypes.length) {
- Iterator it = autowiredBeanNames.iterator();
- for (int i = 0; i < paramTypes.length; i++) {
- String autowiredBeanName = it.next();
- if (beanFactory.containsBean(autowiredBeanName)) {
- if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
- this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
- }
- }
- }
- }
- }
- else {
- this.cachedMethodArguments = null;
- }
- this.cached = true;
- }
- }
- }
- if (arguments != null) {
- ReflectionUtils.makeAccessible(method);
- method.invoke(bean, arguments);
- }
- }
- catch (InvocationTargetException ex) {
- throw ex.getTargetException();
- }
- catch (Throwable ex) {
- throw new BeanCreationException("Could not autowire method: " + method, ex);
- }
- }
-
- private Object[] resolveCachedArguments(String beanName) {
- if (this.cachedMethodArguments == null) {
- return null;
- }
- Object[] arguments = new Object[this.cachedMethodArguments.length];
- for (int i = 0; i < arguments.length; i++) {
- arguments[i] = resolvedCachedArgument(beanName, this.cachedMethodArguments[i]);
- }
- return arguments;
- }
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/ThreadLocalClassloaderBeanPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/ThreadLocalClassloaderBeanPostProcessor.java
deleted file mode 100644
index 22464fad6..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/ThreadLocalClassloaderBeanPostProcessor.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.support;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.PropertyValue;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.core.PriorityOrdered;
-
-/**
- * After the {@link BeanFactory} is created, this post processor will evaluate to see
- * if any of the beans referenced from a job definition (as defined by JSR-352) point
- * to class names instead of bean names. If this is the case, a new {@link BeanDefinition}
- * is added with the name of the class as the bean name.
- *
- * @author Michael Minella
- * @since 3.0
- */
-public class ThreadLocalClassloaderBeanPostProcessor implements BeanFactoryPostProcessor, PriorityOrdered {
- /* (non-Javadoc)
- * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
- */
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- String[] beanNames = beanFactory.getBeanDefinitionNames();
-
- for (String curName : beanNames) {
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(curName);
- PropertyValue[] values = beanDefinition.getPropertyValues().getPropertyValues();
-
- for (PropertyValue propertyValue : values) {
- Object value = propertyValue.getValue();
-
- if(value instanceof RuntimeBeanReference) {
- RuntimeBeanReference ref = (RuntimeBeanReference) value;
- if(!beanFactory.containsBean(ref.getBeanName())) {
- AbstractBeanDefinition newBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(ref.getBeanName()).getBeanDefinition();
- newBeanDefinition.setScope("step");
- ((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(ref.getBeanName(), newBeanDefinition);
- }
- }
- }
- }
- }
-
- /**
- * Sets this {@link BeanFactoryPostProcessor} to the lowest precedence so that
- * it is executed as late as possible in the chain of {@link BeanFactoryPostProcessor}s
- */
- @Override
- public int getOrder() {
- return PriorityOrdered.LOWEST_PRECEDENCE;
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/package-info.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/package-info.java
deleted file mode 100644
index bd359dd44..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Extensions of Spring components to support JSR-352 functionality.
- *
- * @author Michael Minella
- * @author Mahmoud Ben Hassine
- */
-@NonNullApi
-package org.springframework.batch.core.jsr.configuration.support;
-
-import org.springframework.lang.NonNullApi;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/BatchParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/BatchParser.java
deleted file mode 100644
index dce8a0d94..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/BatchParser.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
-
-/**
- * Parser used to parse the batch.xml file as defined in JSR-352. It is not
- * recommended to use the batch.xml approach with Spring to manage bean instantiation.
- * It is recommended that standard Spring bean configurations (via XML or Java Config)
- * be used.
- *
- * @author Michael Minella
- * @since 3.0
- */
-public class BatchParser extends AbstractBeanDefinitionParser {
-
- private static final Log logger = LogFactory.getLog(BatchParser.class);
-
- @Override
- protected boolean shouldGenerateIdAsFallback() {
- return true;
- }
-
- @Override
- protected AbstractBeanDefinition parseInternal(Element element,
- ParserContext parserContext) {
- BeanDefinitionRegistry registry = parserContext.getRegistry();
-
- parseRefElements(element, registry);
-
- return null;
- }
-
- private void parseRefElements(Element element,
- BeanDefinitionRegistry registry) {
- List beanElements = DomUtils.getChildElementsByTagName(element, "ref");
-
- if(beanElements.size() > 0) {
- for (Element curElement : beanElements) {
- AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(curElement.getAttribute("class"))
- .getBeanDefinition();
-
- beanDefinition.setScope("step");
-
- String beanName = curElement.getAttribute("id");
-
- if(!registry.containsBeanDefinition(beanName)) {
- registry.registerBeanDefinition(beanName, beanDefinition);
- } else {
- if (logger.isInfoEnabled()) {
- logger.info("Ignoring batch.xml bean definition for " + beanName + " because another bean of the same name has been registered");
- }
- }
- }
- }
-
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/BatchletParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/BatchletParser.java
deleted file mode 100644
index 953449ff9..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/BatchletParser.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2013-2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import org.springframework.batch.core.jsr.configuration.support.BatchArtifactType;
-import org.springframework.batch.core.step.tasklet.Tasklet;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Element;
-
-/**
- * Parser for the <batchlet /> tag defined in JSR-352. The current state
- * of this parser parses a batchlet element into a {@link Tasklet} (the ref
- * attribute is expected to point to an implementation of Tasklet).
- *
- * @author Michael Minella
- * @author Chris Schaefer
- * @since 3.0
- */
-public class BatchletParser extends AbstractSingleBeanDefinitionParser {
- private static final String REF = "ref";
-
- public void parseBatchlet(Element batchletElement, AbstractBeanDefinition bd, ParserContext parserContext, String stepName) {
- bd.setBeanClass(StepFactoryBean.class);
- bd.setAttribute("isNamespaceStep", false);
-
- String taskletRef = batchletElement.getAttribute(REF);
-
- if (StringUtils.hasText(taskletRef)) {
- bd.getPropertyValues().addPropertyValue("stepTasklet", new RuntimeBeanReference(taskletRef));
- }
-
- bd.setRole(BeanDefinition.ROLE_SUPPORT);
- bd.setSource(parserContext.extractSource(batchletElement));
-
- new PropertyParser(taskletRef, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(batchletElement);
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/ChunkParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/ChunkParser.java
deleted file mode 100644
index 9f12c65d5..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/ChunkParser.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2013-2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import java.util.List;
-
-import org.springframework.batch.core.configuration.xml.ExceptionElementParser;
-import org.springframework.batch.core.jsr.configuration.support.BatchArtifactType;
-import org.springframework.batch.core.step.item.ChunkOrientedTasklet;
-import org.springframework.batch.item.ItemProcessor;
-import org.springframework.batch.item.ItemReader;
-import org.springframework.batch.item.ItemWriter;
-import org.springframework.beans.MutablePropertyValues;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.config.TypedStringValue;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.ManagedList;
-import org.springframework.beans.factory.support.ManagedMap;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.StringUtils;
-import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Parser for the <chunk /> element as specified in JSR-352. The current state
- * parses a chunk element into it's related batch artifacts ({@link ChunkOrientedTasklet}, {@link ItemReader},
- * {@link ItemProcessor}, and {@link ItemWriter}).
- *
- * @author Michael Minella
- * @author Chris Schaefer
- * @since 3.0
- *
- */
-public class ChunkParser {
- private static final String TIME_LIMIT_ATTRIBUTE = "time-limit";
- private static final String ITEM_COUNT_ATTRIBUTE = "item-count";
- private static final String CHECKPOINT_ALGORITHM_ELEMENT = "checkpoint-algorithm";
- private static final String CLASS_ATTRIBUTE = "class";
- private static final String INCLUDE_ELEMENT = "include";
- private static final String NO_ROLLBACK_EXCEPTION_CLASSES_ELEMENT = "no-rollback-exception-classes";
- private static final String RETRYABLE_EXCEPTION_CLASSES_ELEMENT = "retryable-exception-classes";
- private static final String SKIPPABLE_EXCEPTION_CLASSES_ELEMENT = "skippable-exception-classes";
- private static final String WRITER_ELEMENT = "writer";
- private static final String PROCESSOR_ELEMENT = "processor";
- private static final String READER_ELEMENT = "reader";
- private static final String REF_ATTRIBUTE = "ref";
- private static final String RETRY_LIMIT_ATTRIBUTE = "retry-limit";
- private static final String SKIP_LIMIT_ATTRIBUTE = "skip-limit";
- private static final String CUSTOM_CHECKPOINT_POLICY = "custom";
- private static final String ITEM_CHECKPOINT_POLICY = "item";
- private static final String CHECKPOINT_POLICY_ATTRIBUTE = "checkpoint-policy";
-
- public void parse(Element element, AbstractBeanDefinition bd, ParserContext parserContext, String stepName) {
- MutablePropertyValues propertyValues = bd.getPropertyValues();
- bd.setBeanClass(StepFactoryBean.class);
- bd.setAttribute("isNamespaceStep", false);
-
- propertyValues.addPropertyValue("hasChunkElement", Boolean.TRUE);
-
- String checkpointPolicy = element.getAttribute(CHECKPOINT_POLICY_ATTRIBUTE);
- if(StringUtils.hasText(checkpointPolicy)) {
- if(checkpointPolicy.equals(ITEM_CHECKPOINT_POLICY)) {
- String itemCount = element.getAttribute(ITEM_COUNT_ATTRIBUTE);
- if (StringUtils.hasText(itemCount)) {
- propertyValues.addPropertyValue("commitInterval", itemCount);
- } else {
- propertyValues.addPropertyValue("commitInterval", "10");
- }
-
- parseSimpleAttribute(element, propertyValues, TIME_LIMIT_ATTRIBUTE, "timeout");
- } else if(checkpointPolicy.equals(CUSTOM_CHECKPOINT_POLICY)) {
- parseCustomCheckpointAlgorithm(element, parserContext, propertyValues, stepName);
- }
- } else {
- String itemCount = element.getAttribute(ITEM_COUNT_ATTRIBUTE);
- if (StringUtils.hasText(itemCount)) {
- propertyValues.addPropertyValue("commitInterval", itemCount);
- } else {
- propertyValues.addPropertyValue("commitInterval", "10");
- }
-
- parseSimpleAttribute(element, propertyValues, TIME_LIMIT_ATTRIBUTE, "timeout");
- }
-
- parseSimpleAttribute(element, propertyValues, SKIP_LIMIT_ATTRIBUTE, "skipLimit");
- parseSimpleAttribute(element, propertyValues, RETRY_LIMIT_ATTRIBUTE, "retryLimit");
-
- NodeList children = element.getChildNodes();
- for (int i = 0; i < children.getLength(); i++) {
- Node nd = children.item(i);
-
- parseChildElement(element, parserContext, propertyValues, nd, stepName);
- }
- }
-
- private void parseSimpleAttribute(Element element,
- MutablePropertyValues propertyValues, String attributeName, String propertyName) {
- String propertyValue = element.getAttribute(attributeName);
- if (StringUtils.hasText(propertyValue)) {
- propertyValues.addPropertyValue(propertyName, propertyValue);
- }
- }
-
- private void parseChildElement(Element element, ParserContext parserContext,
- MutablePropertyValues propertyValues, Node nd, String stepName) {
- if (nd instanceof Element) {
- Element nestedElement = (Element) nd;
- String name = nestedElement.getLocalName();
- String artifactName = nestedElement.getAttribute(REF_ATTRIBUTE);
-
- if(name.equals(READER_ELEMENT)) {
- if (StringUtils.hasText(artifactName)) {
- propertyValues.addPropertyValue("stepItemReader", new RuntimeBeanReference(artifactName));
- }
-
- new PropertyParser(artifactName, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(nestedElement);
- } else if(name.equals(PROCESSOR_ELEMENT)) {
- if (StringUtils.hasText(artifactName)) {
- propertyValues.addPropertyValue("stepItemProcessor", new RuntimeBeanReference(artifactName));
- }
-
- new PropertyParser(artifactName, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(nestedElement);
- } else if(name.equals(WRITER_ELEMENT)) {
- if (StringUtils.hasText(artifactName)) {
- propertyValues.addPropertyValue("stepItemWriter", new RuntimeBeanReference(artifactName));
- }
-
- new PropertyParser(artifactName, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(nestedElement);
- } else if(name.equals(SKIPPABLE_EXCEPTION_CLASSES_ELEMENT)) {
- ManagedMap exceptionClasses = new ExceptionElementParser().parse(element, parserContext, SKIPPABLE_EXCEPTION_CLASSES_ELEMENT);
- if(exceptionClasses != null) {
- propertyValues.addPropertyValue("skippableExceptionClasses", exceptionClasses);
- }
- } else if(name.equals(RETRYABLE_EXCEPTION_CLASSES_ELEMENT)) {
- ManagedMap exceptionClasses = new ExceptionElementParser().parse(element, parserContext, RETRYABLE_EXCEPTION_CLASSES_ELEMENT);
- if(exceptionClasses != null) {
- propertyValues.addPropertyValue("retryableExceptionClasses", exceptionClasses);
- }
- } else if(name.equals(NO_ROLLBACK_EXCEPTION_CLASSES_ELEMENT)) {
- //TODO: Update to support excludes
- ManagedList list = new ManagedList<>();
-
- for (Element child : DomUtils.getChildElementsByTagName(nestedElement, INCLUDE_ELEMENT)) {
- String className = child.getAttribute(CLASS_ATTRIBUTE);
- list.add(new TypedStringValue(className, Class.class));
- }
-
- propertyValues.addPropertyValue("noRollbackExceptionClasses", list);
- }
- }
- }
-
- private void parseCustomCheckpointAlgorithm(Element element, ParserContext parserContext, MutablePropertyValues propertyValues, String stepName) {
- List elements = DomUtils.getChildElementsByTagName(element, CHECKPOINT_ALGORITHM_ELEMENT);
-
- if(elements.size() == 1) {
- Element checkpointAlgorithmElement = elements.get(0);
-
- String name = checkpointAlgorithmElement.getAttribute(REF_ATTRIBUTE);
- if(StringUtils.hasText(name)) {
- propertyValues.addPropertyValue("stepChunkCompletionPolicy", new RuntimeBeanReference(name));
- }
-
- new PropertyParser(name, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(checkpointAlgorithmElement);
- } else if(elements.size() > 1){
- parserContext.getReaderContext().error(
- "The element may not appear more than once in a single <"
- + element.getNodeName() + "/>.", element);
- }
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStepFactoryBean.java
deleted file mode 100644
index 3d8dad0f3..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStepFactoryBean.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import jakarta.batch.api.Decider;
-
-import org.springframework.batch.core.Step;
-import org.springframework.batch.core.jsr.step.DecisionStep;
-import org.springframework.batch.core.repository.JobRepository;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.util.Assert;
-
-/**
- * {@link FactoryBean} for creating a {@link DecisionStep}.
- *
- * @author Michael Minella
- * @author Mahmoud Ben Hassine
- * @since 3.0
- */
-public class DecisionStepFactoryBean implements FactoryBean, InitializingBean {
-
- private Decider jsrDecider;
- private String name;
- private JobRepository jobRepository;
-
- /**
- * @param jobRepository All steps need to be able to reference a {@link JobRepository}
- */
- public void setJobRepository(JobRepository jobRepository) {
- this.jobRepository = jobRepository;
- }
-
- /**
- * @param decider a {@link Decider}
- * @throws IllegalArgumentException if the type passed in is not a valid type
- */
- public void setDecider(Decider decider) {
- this.jsrDecider = decider;
- }
-
- /**
- * The name of the state
- *
- * @param name the name to be used by the DecisionStep.
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /* (non-Javadoc)
- * @see org.springframework.beans.factory.FactoryBean#getObject()
- */
- @Override
- public Step getObject() throws Exception {
-
- DecisionStep decisionStep = new DecisionStep(jsrDecider);
- decisionStep.setName(name);
- decisionStep.setJobRepository(jobRepository);
- decisionStep.setAllowStartIfComplete(true);
-
- return decisionStep;
- }
-
- /* (non-Javadoc)
- * @see org.springframework.beans.factory.FactoryBean#getObjectType()
- */
- @Override
- public Class> getObjectType() {
- return DecisionStep.class;
- }
-
- /* (non-Javadoc)
- * @see org.springframework.beans.factory.FactoryBean#isSingleton()
- */
- @Override
- public boolean isSingleton() {
- return true;
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- Assert.isTrue(jsrDecider != null, "A decider implementation is required");
- Assert.notNull(name, "A name is required for a decision state");
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/FlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/FlowParser.java
deleted file mode 100644
index 1b4fe3341..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/FlowParser.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright 2013-2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.springframework.batch.core.configuration.xml.AbstractFlowParser;
-import org.springframework.batch.core.job.flow.FlowExecutionStatus;
-import org.springframework.batch.core.jsr.job.flow.support.JsrFlow;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.ManagedList;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.StringUtils;
-import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Parses flows as defined in JSR-352. The current state parses a flow
- * as it is within a regular Spring Batch job/flow.
- *
- * @author Michael Minella
- * @author Chris Schaefer
- * @since 3.0
- */
-public class FlowParser extends AbstractFlowParser {
- private static final String NEXT_ATTRIBUTE = "next";
- private static final String EXIT_STATUS_ATTRIBUTE = "exit-status";
- private static final List TRANSITION_TYPES = new ArrayList<>();
-
- static {
- TRANSITION_TYPES.add(NEXT_ELE);
- TRANSITION_TYPES.add(STOP_ELE);
- TRANSITION_TYPES.add(END_ELE);
- TRANSITION_TYPES.add(FAIL_ELE);
- }
-
- private String flowName;
- private String jobFactoryRef;
- private StepParser stepParser = new StepParser();
-
- /**
- * @param flowName The name of the flow
- * @param jobFactoryRef The bean name for the job factory
- */
- public FlowParser(String flowName, String jobFactoryRef) {
- super.setJobFactoryRef(jobFactoryRef);
- this.jobFactoryRef = jobFactoryRef;
- this.flowName = flowName;
- }
-
- @Override
- protected Class> getBeanClass(Element element) {
- return JsrFlowFactoryBean.class;
- }
-
- @Override
- protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
- builder.getRawBeanDefinition().setAttribute("flowName", flowName);
- builder.addPropertyValue("name", flowName);
- builder.addPropertyValue("flowType", JsrFlow.class);
-
- List stateTransitions = new ArrayList<>();
-
- Map> reachableElementMap = new HashMap<>();
- String startElement = null;
- NodeList children = element.getChildNodes();
- for (int i = 0; i < children.getLength(); i++) {
- Node node = children.item(i);
- if (node instanceof Element) {
- String nodeName = node.getLocalName();
- Element child = (Element) node;
- if (nodeName.equals(STEP_ELE)) {
- stateTransitions.addAll(stepParser.parse(child, parserContext, builder));
- } else if(nodeName.equals(SPLIT_ELE)) {
- stateTransitions.addAll(new JsrSplitParser(flowName).parse(child, parserContext));
- } else if(nodeName.equals(DECISION_ELE)) {
- stateTransitions.addAll(new JsrDecisionParser().parse(child, parserContext, flowName));
- } else if(nodeName.equals(FLOW_ELE)) {
- stateTransitions.addAll(parseFlow(child, parserContext, builder));
- }
- }
- }
-
- Set allReachableElements = new HashSet<>();
- findAllReachableElements(startElement, reachableElementMap, allReachableElements);
- for (String elementId : reachableElementMap.keySet()) {
- if (!allReachableElements.contains(elementId)) {
- parserContext.getReaderContext().error("The element [" + elementId + "] is unreachable", element);
- }
- }
-
- ManagedList managedList = new ManagedList<>();
- managedList.addAll(stateTransitions);
- builder.addPropertyValue("stateTransitions", managedList);
- }
-
- private Collection parseFlow(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
- String idAttribute = element.getAttribute(ID_ATTRIBUTE);
-
- BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder
- .genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.FlowState");
-
- FlowParser flowParser = new FlowParser(idAttribute, jobFactoryRef);
-
- stateBuilder.addConstructorArgValue(flowParser.parse(element, parserContext));
- stateBuilder.addConstructorArgValue(idAttribute);
-
- builder.getRawBeanDefinition().setAttribute("flowName", idAttribute);
- builder.addPropertyValue("name", idAttribute);
-
- doParse(element, parserContext, builder);
- builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-
- return FlowParser.getNextElements(parserContext, null, stateBuilder.getBeanDefinition(), element);
- }
-
- public static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef,
- Element element) {
- return getNextElements(parserContext, null, stateDef, element);
- }
-
- public static Collection getNextElements(ParserContext parserContext, String stepId,
- BeanDefinition stateDef, Element element) {
-
- Collection list = new ArrayList<>();
-
- boolean transitionElementExists = false;
- boolean failedTransitionElementExists = false;
-
- List childElements = DomUtils.getChildElements(element);
- for(Element childElement : childElements) {
- if(isChildElementTransitionElement(childElement)) {
- list.addAll(parseTransitionElement(childElement, stepId, stateDef, parserContext));
- failedTransitionElementExists = failedTransitionElementExists || hasFailedTransitionElement(childElement);
- transitionElementExists = true;
- }
- }
-
- String shortNextAttribute = element.getAttribute(NEXT_ATTRIBUTE);
- boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute);
-
- if (!transitionElementExists) {
- list.addAll(createTransition(FlowExecutionStatus.FAILED, FlowExecutionStatus.FAILED.getName(), null, null,
- stateDef, parserContext, false));
- list.addAll(createTransition(FlowExecutionStatus.UNKNOWN, FlowExecutionStatus.UNKNOWN.getName(), null, null,
- stateDef, parserContext, false));
- }
-
- if (hasNextAttribute) {
- if (transitionElementExists && !failedTransitionElementExists) {
- list.addAll(createTransition(FlowExecutionStatus.FAILED, FlowExecutionStatus.FAILED.getName(), null, null,
- stateDef, parserContext, false));
- }
-
- list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute));
- } else {
- list.addAll(createTransition(FlowExecutionStatus.COMPLETED, FlowExecutionStatus.COMPLETED.getName(), null, null, stateDef, parserContext,
- false));
- }
-
- return list;
- }
-
- private static boolean isChildElementTransitionElement(Element childElement) {
- return TRANSITION_TYPES.contains(childElement.getLocalName());
- }
-
- private static boolean hasFailedTransitionElement(Element childName) {
- return FAIL_ELE.equals(childName.getLocalName());
- }
-
- protected static Collection parseTransitionElement(Element transitionElement, String stateId,
- BeanDefinition stateDef, ParserContext parserContext) {
- FlowExecutionStatus status = getBatchStatusFromEndTransitionName(transitionElement.getNodeName());
- String onAttribute = transitionElement.getAttribute(ON_ATTR);
- String restartAttribute = transitionElement.getAttribute(RESTART_ATTR);
- String nextAttribute = transitionElement.getAttribute(TO_ATTR);
-
- if (!StringUtils.hasText(nextAttribute)) {
- nextAttribute = restartAttribute;
- }
- String exitCodeAttribute = transitionElement.getAttribute(EXIT_STATUS_ATTRIBUTE);
-
- return createTransition(status, onAttribute, nextAttribute, restartAttribute, exitCodeAttribute, stateDef, parserContext, false);
- }
-
- /**
- * @param status The batch status that this transition will set. Use
- * BatchStatus.UNKNOWN if not applicable.
- * @param on The pattern that this transition should match. Use null for
- * "no restriction" (same as "*").
- * @param next The state to which this transition should go. Use null if not
- * applicable.
- * @param restart The restart attribute this transition will set.
- * @param exitCode The exit code that this transition will set. Use null to
- * default to batchStatus.
- * @param stateDef The bean definition for the current state
- * @param parserContext the parser context for the bean factory
- * @param abandon the abandon state this transition will set.
- * @return a collection of
- * {@link org.springframework.batch.core.job.flow.support.StateTransition}
- * references
- */
- protected static Collection createTransition(FlowExecutionStatus status, String on, String next,
- String restart, String exitCode, BeanDefinition stateDef, ParserContext parserContext, boolean abandon) {
-
- BeanDefinition endState = null;
-
- if (status.isEnd()) {
-
- BeanDefinitionBuilder endBuilder = BeanDefinitionBuilder
- .genericBeanDefinition("org.springframework.batch.core.jsr.job.flow.support.state.JsrEndState");
-
- boolean exitCodeExists = StringUtils.hasText(exitCode);
-
- endBuilder.addConstructorArgValue(status);
-
- endBuilder.addConstructorArgValue(exitCodeExists ? exitCode : status.getName());
-
- String endName = (status == FlowExecutionStatus.STOPPED ? STOP_ELE
- : status == FlowExecutionStatus.FAILED ? FAIL_ELE : END_ELE)
- + (endCounter++);
- endBuilder.addConstructorArgValue(endName);
-
- endBuilder.addConstructorArgValue(restart);
-
- endBuilder.addConstructorArgValue(abandon);
-
- endBuilder.addConstructorArgReference("jobRepository");
-
- String nextOnEnd = exitCodeExists ? null : next;
- endState = getStateTransitionReference(parserContext, endBuilder.getBeanDefinition(), null, nextOnEnd);
- next = endName;
-
- }
-
- Collection list = new ArrayList<>();
- list.add(getStateTransitionReference(parserContext, stateDef, on, next));
-
- if(StringUtils.hasText(restart)) {
- list.add(getStateTransitionReference(parserContext, stateDef, on + ".RESTART", restart));
- }
-
- if (endState != null) {
- //
- // Must be added after the state to ensure that the state is the
- // first in the list
- //
- list.add(endState);
- }
- return list;
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JobFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JobFactoryBean.java
deleted file mode 100644
index f92ac09e2..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JobFactoryBean.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import jakarta.batch.api.listener.JobListener;
-
-import org.springframework.batch.core.JobExecutionListener;
-import org.springframework.batch.core.JobParametersIncrementer;
-import org.springframework.batch.core.JobParametersValidator;
-import org.springframework.batch.core.explore.JobExplorer;
-import org.springframework.batch.core.job.flow.Flow;
-import org.springframework.batch.core.job.flow.FlowJob;
-import org.springframework.batch.core.jsr.JobListenerAdapter;
-import org.springframework.batch.core.jsr.job.flow.JsrFlowJob;
-import org.springframework.batch.core.repository.JobRepository;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.SmartFactoryBean;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
-/**
- * This {@link FactoryBean} is used by the JSR-352 namespace parser to create
- * {@link FlowJob} objects. It stores all of the properties that are
- * configurable on the <job/>.
- *
- * @author Michael Minella
- * @author Mahmoud Ben Hassine
- * @since 3.0
- */
-public class JobFactoryBean implements SmartFactoryBean {
-
- private String name;
-
- private Boolean restartable;
-
- private JobRepository jobRepository;
-
- private JobParametersValidator jobParametersValidator;
-
- private JobExecutionListener[] jobExecutionListeners;
-
- private JobParametersIncrementer jobParametersIncrementer;
-
- private Flow flow;
-
- private JobExplorer jobExplorer;
-
- public JobFactoryBean(String name) {
- this.name = name;
- }
-
- @Override
- public final FlowJob getObject() throws Exception {
- Assert.isTrue(StringUtils.hasText(name), "The job must have an id.");
- JsrFlowJob flowJob = new JsrFlowJob(name);
- flowJob.setJobExplorer(jobExplorer);
-
- if (restartable != null) {
- flowJob.setRestartable(restartable);
- }
-
- if (jobRepository != null) {
- flowJob.setJobRepository(jobRepository);
- }
-
- if (jobParametersValidator != null) {
- flowJob.setJobParametersValidator(jobParametersValidator);
- }
-
- if (jobExecutionListeners != null) {
- flowJob.setJobExecutionListeners(jobExecutionListeners);
- }
-
- if (jobParametersIncrementer != null) {
- flowJob.setJobParametersIncrementer(jobParametersIncrementer);
- }
-
- if (flow != null) {
- flowJob.setFlow(flow);
- }
-
- flowJob.afterPropertiesSet();
- return flowJob;
- }
-
- public void setJobExplorer(JobExplorer jobExplorer) {
- this.jobExplorer = jobExplorer;
- }
-
- public void setRestartable(Boolean restartable) {
- this.restartable = restartable;
- }
-
- public void setJobRepository(JobRepository jobRepository) {
- this.jobRepository = jobRepository;
- }
-
- public void setJobParametersValidator(JobParametersValidator jobParametersValidator) {
- this.jobParametersValidator = jobParametersValidator;
- }
-
- public JobRepository getJobRepository() {
- return this.jobRepository;
- }
-
- public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIncrementer) {
- this.jobParametersIncrementer = jobParametersIncrementer;
- }
-
- public void setFlow(Flow flow) {
- this.flow = flow;
- }
-
- @Override
- public Class getObjectType() {
- return FlowJob.class;
- }
-
- @Override
- public boolean isSingleton() {
- return true;
- }
-
- @Override
- public boolean isEagerInit() {
- return true;
- }
-
- @Override
- public boolean isPrototype() {
- return false;
- }
-
- /**
- * Addresses wrapping {@link JobListener} as needed to be used with
- * the framework.
- *
- * @param jobListeners a list of all job listeners
- */
- public void setJobExecutionListeners(Object[] jobListeners) {
- if(jobListeners != null) {
- JobExecutionListener[] listeners = new JobExecutionListener[jobListeners.length];
-
- for(int i = 0; i < jobListeners.length; i++) {
- Object curListener = jobListeners[i];
- if(curListener instanceof JobExecutionListener) {
- listeners[i] = (JobExecutionListener) curListener;
- } else if(curListener instanceof JobListener){
- listeners[i] = new JobListenerAdapter((JobListener) curListener);
- }
- }
-
- this.jobExecutionListeners = listeners;
- }
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrBeanDefinitionDocumentReader.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrBeanDefinitionDocumentReader.java
deleted file mode 100644
index 2e86e4dfc..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrBeanDefinitionDocumentReader.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.batch.core.jsr.configuration.support.JsrExpressionParser;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader;
-import org.springframework.util.ClassUtils;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.ls.DOMImplementationLS;
-import org.w3c.dom.traversal.DocumentTraversal;
-import org.w3c.dom.traversal.NodeFilter;
-import org.w3c.dom.traversal.NodeIterator;
-
-/**
- *
- * {@link DefaultBeanDefinitionDocumentReader} extension to hook into the pre processing of the provided
- * XML document, ensuring any references to property operators such as jobParameters and jobProperties are
- * resolved prior to loading the context. Since we know these initial values upfront, doing this transformation
- * allows us to ensure values are retrieved in their resolved form prior to loading the context and property
- * operators can be used on any element. This document reader will also look for references to artifacts by
- * the same name and create new bean definitions to provide the ability to create new instances.
- *
- *
- * @author Chris Schaefer
- * @author Mahmoud Ben Hassine
- * @since 3.0
- */
-public class JsrBeanDefinitionDocumentReader extends DefaultBeanDefinitionDocumentReader {
- private static final String NULL = "null";
- private static final String ROOT_JOB_ELEMENT_NAME = "job";
- private static final String JOB_PROPERTY_ELEMENT_NAME = "property";
- private static final String JOB_PROPERTIES_ELEMENT_NAME = "properties";
- private static final String JOB_PROPERTY_ELEMENT_NAME_ATTRIBUTE = "name";
- private static final String JOB_PROPERTY_ELEMENT_VALUE_ATTRIBUTE = "value";
- private static final String JOB_PROPERTIES_KEY_NAME = "jobProperties";
- private static final String JOB_PARAMETERS_KEY_NAME = "jobParameters";
- private static final String JOB_PARAMETERS_BEAN_DEFINITION_NAME = "jsr_jobParameters";
- private static final Log LOG = LogFactory.getLog(JsrBeanDefinitionDocumentReader.class);
- private static final Pattern PROPERTY_KEY_SEPARATOR = Pattern.compile("'([^']*?)'");
- private static final Pattern OPERATOR_PATTERN = Pattern.compile("(#\\{(job(Properties|Parameters))[^}]+\\})");
-
- private BeanDefinitionRegistry beanDefinitionRegistry;
- private JsrExpressionParser expressionParser = new JsrExpressionParser();
- private Map propertyMap = new HashMap<>();
-
- /**
- *
- * Creates a new {@link JsrBeanDefinitionDocumentReader} instance.
- *
- */
- public JsrBeanDefinitionDocumentReader() { }
-
- /**
- *
- * Create a new {@link JsrBeanDefinitionDocumentReader} instance with the provided
- * {@link BeanDefinitionRegistry}.
- *
- *
- * @param beanDefinitionRegistry the {@link BeanDefinitionRegistry} to use
- */
- public JsrBeanDefinitionDocumentReader(BeanDefinitionRegistry beanDefinitionRegistry) {
- this.beanDefinitionRegistry = beanDefinitionRegistry;
- }
-
- @Override
- protected void preProcessXml(Element root) {
- if (ROOT_JOB_ELEMENT_NAME.equals(root.getLocalName())) {
- initProperties(root);
- transformDocument(root);
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Transformed XML from preProcessXml: " + elementToString(root));
- }
- }
- }
-
- protected void initProperties(Element root) {
- propertyMap.put(JOB_PARAMETERS_KEY_NAME, initJobParameters());
- propertyMap.put(JOB_PROPERTIES_KEY_NAME, initJobProperties(root));
-
- resolvePropertyValues(propertyMap.get(JOB_PARAMETERS_KEY_NAME));
- resolvePropertyValues(propertyMap.get(JOB_PROPERTIES_KEY_NAME));
- }
-
- private Properties initJobParameters() {
- Properties jobParameters = new Properties();
-
- if (getBeanDefinitionRegistry().containsBeanDefinition(JOB_PARAMETERS_BEAN_DEFINITION_NAME)) {
- BeanDefinition beanDefinition = getBeanDefinitionRegistry().getBeanDefinition(JOB_PARAMETERS_BEAN_DEFINITION_NAME);
-
- Properties properties = (Properties) beanDefinition.getConstructorArgumentValues()
- .getGenericArgumentValue(Properties.class)
- .getValue();
-
- if (properties == null) {
- return new Properties();
- }
-
- Enumeration> propertyNames = properties.propertyNames();
-
- while(propertyNames.hasMoreElements()) {
- String curName = (String) propertyNames.nextElement();
- jobParameters.put(curName, properties.getProperty(curName));
- }
- }
-
- return jobParameters;
- }
-
- private Properties initJobProperties(Element root) {
- Properties properties = new Properties();
- Node propertiesNode = root.getElementsByTagName(JOB_PROPERTIES_ELEMENT_NAME).item(0);
-
- if(propertiesNode != null) {
- NodeList children = propertiesNode.getChildNodes();
-
- for(int i=0; i < children.getLength(); i++) {
- Node child = children.item(i);
-
- if(JOB_PROPERTY_ELEMENT_NAME.equals(child.getLocalName())) {
- NamedNodeMap attributes = child.getAttributes();
- Node name = attributes.getNamedItem(JOB_PROPERTY_ELEMENT_NAME_ATTRIBUTE);
- Node value = attributes.getNamedItem(JOB_PROPERTY_ELEMENT_VALUE_ATTRIBUTE);
-
- properties.setProperty(name.getNodeValue(), value.getNodeValue());
- }
- }
- }
-
- return properties;
- }
-
- private void resolvePropertyValues(Properties properties) {
- for (String propertyKey : properties.stringPropertyNames()) {
- String resolvedPropertyValue = resolvePropertyValue(properties.getProperty(propertyKey));
-
- if(!properties.getProperty(propertyKey).equals(resolvedPropertyValue)) {
- properties.setProperty(propertyKey, resolvedPropertyValue);
- }
- }
- }
-
- private String resolvePropertyValue(String propertyValue) {
- String resolvedValue = resolveValue(propertyValue);
-
- Matcher jobParameterMatcher = OPERATOR_PATTERN.matcher(resolvedValue);
-
- while (jobParameterMatcher.find()) {
- resolvedValue = resolvePropertyValue(resolvedValue);
- }
-
- return resolvedValue;
- }
-
- private String resolveValue(String value) {
- StringBuffer valueBuffer = new StringBuffer();
- Matcher jobParameterMatcher = OPERATOR_PATTERN.matcher(value);
-
- while (jobParameterMatcher.find()) {
- Matcher jobParameterKeyMatcher = PROPERTY_KEY_SEPARATOR.matcher(jobParameterMatcher.group(1));
-
- if (jobParameterKeyMatcher.find()) {
- String propertyType = jobParameterMatcher.group(2);
- String extractedProperty = jobParameterKeyMatcher.group(1);
-
- Properties properties = propertyMap.get(propertyType);
-
- if(properties == null) {
- throw new IllegalArgumentException("Unknown property type: " + propertyType);
- }
-
- String resolvedProperty = properties.getProperty(extractedProperty, NULL);
-
- if (NULL.equals(resolvedProperty) && LOG.isInfoEnabled()) {
- LOG.info(propertyType + " with key of: " + extractedProperty + " could not be resolved. Possible configuration error?");
- }
-
- jobParameterMatcher.appendReplacement(valueBuffer, resolvedProperty);
- }
- }
-
- jobParameterMatcher.appendTail(valueBuffer);
- String resolvedValue = valueBuffer.toString();
-
- if (NULL.equals(resolvedValue)) {
- return "";
- }
-
- return expressionParser.parseExpression(resolvedValue);
- }
-
- private BeanDefinitionRegistry getBeanDefinitionRegistry() {
- return beanDefinitionRegistry != null ? beanDefinitionRegistry : getReaderContext().getRegistry();
- }
-
- private void transformDocument(Element root) {
- DocumentTraversal traversal = (DocumentTraversal) root.getOwnerDocument();
- NodeIterator iterator = traversal.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, null, true);
-
- BeanDefinitionRegistry registry = getBeanDefinitionRegistry();
- Map referenceCountMap = new HashMap<>();
-
- for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
- NamedNodeMap map = n.getAttributes();
-
- if (map.getLength() > 0) {
- for (int i = 0; i < map.getLength(); i++) {
- Node node = map.item(i);
-
- String nodeName = node.getNodeName();
- String nodeValue = node.getNodeValue();
- String resolvedValue = resolveValue(nodeValue);
- String newNodeValue = resolvedValue;
-
- if("ref".equals(nodeName)) {
- if(!referenceCountMap.containsKey(resolvedValue)) {
- referenceCountMap.put(resolvedValue, 0);
- }
-
- boolean isClass = isClass(resolvedValue);
- Integer referenceCount = referenceCountMap.get(resolvedValue);
-
- // possibly fully qualified class name in ref tag in the JSL or pointer to bean/artifact ref.
- if(isClass && !registry.containsBeanDefinition(resolvedValue)) {
- AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(resolvedValue)
- .getBeanDefinition();
- beanDefinition.setScope("step");
- registry.registerBeanDefinition(resolvedValue, beanDefinition);
-
- newNodeValue = resolvedValue;
- } else {
- if(registry.containsBeanDefinition(resolvedValue)) {
- referenceCount++;
- referenceCountMap.put(resolvedValue, referenceCount);
-
- newNodeValue = resolvedValue + referenceCount;
-
- BeanDefinition beanDefinition = registry.getBeanDefinition(resolvedValue);
- registry.registerBeanDefinition(newNodeValue, beanDefinition);
- }
- }
- }
-
- if(!nodeValue.equals(newNodeValue)) {
- node.setNodeValue(newNodeValue);
- }
- }
- } else {
- String nodeValue = n.getTextContent();
- String resolvedValue = resolveValue(nodeValue);
-
- if(!nodeValue.equals(resolvedValue)) {
- n.setTextContent(resolvedValue);
- }
- }
- }
- }
-
- private boolean isClass(String className) {
- try {
- Class.forName(className, false, ClassUtils.getDefaultClassLoader());
- } catch (ClassNotFoundException e) {
- return false;
- }
-
- return true;
- }
-
- protected Properties getJobParameters() {
- return propertyMap.get(JOB_PARAMETERS_KEY_NAME);
- }
-
- protected Properties getJobProperties() {
- return propertyMap.get(JOB_PROPERTIES_KEY_NAME);
- }
-
- private String elementToString(Element root) {
- DOMImplementationLS domImplLS = (DOMImplementationLS) root.getOwnerDocument().getImplementation();
- return domImplLS.createLSSerializer().writeToString(root);
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrDecisionParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrDecisionParser.java
deleted file mode 100644
index 78ddaaa34..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrDecisionParser.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2013-2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import java.util.Collection;
-
-import org.springframework.batch.core.job.flow.JobExecutionDecider;
-import org.springframework.batch.core.jsr.configuration.support.BatchArtifactType;
-import org.springframework.batch.core.jsr.job.flow.support.state.JsrStepState;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.parsing.BeanComponentDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Element;
-
-/**
- * Parser for the <decision /> element as specified in JSR-352. The current state
- * parses a decision element and assumes that it refers to a {@link JobExecutionDecider}
- *
- * @author Michael Minella
- * @author Chris Schaefer
- * @since 3.0
- */
-public class JsrDecisionParser {
-
- private static final String ID_ATTRIBUTE = "id";
- private static final String REF_ATTRIBUTE = "ref";
-
- public Collection parse(Element element, ParserContext parserContext, String jobFactoryRef) {
- BeanDefinitionBuilder factoryBuilder = BeanDefinitionBuilder.genericBeanDefinition();
- AbstractBeanDefinition factoryDefinition = factoryBuilder.getRawBeanDefinition();
- factoryDefinition.setBeanClass(DecisionStepFactoryBean.class);
-
- BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition(JsrStepState.class);
-
- String idAttribute = element.getAttribute(ID_ATTRIBUTE);
-
- parserContext.registerBeanComponent(new BeanComponentDefinition(factoryDefinition, idAttribute));
- stateBuilder.addConstructorArgReference(idAttribute);
-
- String refAttribute = element.getAttribute(REF_ATTRIBUTE);
- factoryDefinition.getPropertyValues().add("decider", new RuntimeBeanReference(refAttribute));
- factoryDefinition.getPropertyValues().add("name", idAttribute);
-
- if(StringUtils.hasText(jobFactoryRef)) {
- factoryDefinition.setAttribute("jobParserJobFactoryBeanRef", jobFactoryRef);
- }
-
- new PropertyParser(refAttribute, parserContext, BatchArtifactType.STEP_ARTIFACT, idAttribute).parseProperties(element);
-
- return FlowParser.getNextElements(parserContext, stateBuilder.getBeanDefinition(), element);
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrFlowFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrFlowFactoryBean.java
deleted file mode 100644
index 3238a2b06..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrFlowFactoryBean.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean;
-import org.springframework.batch.core.job.flow.State;
-import org.springframework.batch.core.jsr.job.flow.support.state.JsrStepState;
-
-/**
- * Extension to the {@link SimpleFlowFactoryBean} that provides {@link org.springframework.batch.core.jsr.job.flow.support.state.JsrStepState}
- * implementations for JSR-352 based jobs.
- *
- * @author Michael Minella
- * @since 3.0
- */
-public class JsrFlowFactoryBean extends SimpleFlowFactoryBean {
-
- /* (non-Javadoc)
- * @see org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean#createNewStepState(org.springframework.batch.core.job.flow.State, java.lang.String, java.lang.String)
- */
- @Override
- protected State createNewStepState(State state, String oldName,
- String stateName) {
- return new JsrStepState(stateName, ((JsrStepState) state).getStep(oldName));
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrJobListenerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrJobListenerFactoryBean.java
deleted file mode 100644
index 2349d759f..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrJobListenerFactoryBean.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import jakarta.batch.api.listener.JobListener;
-
-import org.springframework.batch.core.JobExecutionListener;
-import org.springframework.batch.core.jsr.JsrJobListenerMetaData;
-import org.springframework.batch.core.listener.JobListenerMetaData;
-import org.springframework.batch.core.listener.ListenerMetaData;
-import org.springframework.beans.factory.FactoryBean;
-
-/**
- * This {@link FactoryBean} is used by the JSR-352 namespace parser to create
- * {@link JobExecutionListener} objects.
- *
- * @author Michael Minella
- * @author Mahmoud Ben Hassine
- * @since 3.0
- */
-public class JsrJobListenerFactoryBean extends org.springframework.batch.core.listener.JobListenerFactoryBean {
-
- @Override
- public Class> getObjectType() {
- return JobListener.class;
- }
-
- @Override
- protected ListenerMetaData[] getMetaDataValues() {
- List values = new ArrayList<>();
- Collections.addAll(values, JobListenerMetaData.values());
- Collections.addAll(values, JsrJobListenerMetaData.values());
-
- return values.toArray(new ListenerMetaData[0]);
- }
-
- @Override
- protected ListenerMetaData getMetaDataFromPropertyName(String propertyName) {
- ListenerMetaData result = JobListenerMetaData.fromPropertyName(propertyName);
-
- if(result == null) {
- result = JsrJobListenerMetaData.fromPropertyName(propertyName);
- }
-
- return result;
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrJobParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrJobParser.java
deleted file mode 100644
index 43334726b..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrJobParser.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2013-2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import org.springframework.batch.core.configuration.xml.CoreNamespaceUtils;
-import org.springframework.batch.core.jsr.JsrStepContextFactoryBean;
-import org.springframework.batch.core.jsr.configuration.support.BatchArtifactType;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Element;
-
-/**
- * Parses a <job /> tag as defined in JSR-352. Current state parses into
- * the standard Spring Batch artifacts.
- *
- * @author Michael Minella
- * @author Chris Schaefer
- * @since 3.0
- */
-public class JsrJobParser extends AbstractSingleBeanDefinitionParser {
- private static final String ID_ATTRIBUTE = "id";
- private static final String RESTARTABLE_ATTRIBUTE = "restartable";
-
- @Override
- protected Class getBeanClass(Element element) {
- return JobFactoryBean.class;
- }
-
- @Override
- protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
- CoreNamespaceUtils.autoregisterBeansForNamespace(parserContext, parserContext.extractSource(element));
- JsrNamespaceUtils.autoregisterJsrBeansForNamespace(parserContext);
-
- String jobName = element.getAttribute(ID_ATTRIBUTE);
-
- builder.setLazyInit(true);
-
- builder.addConstructorArgValue(jobName);
-
- builder.addPropertyReference("jobExplorer", "jobExplorer");
-
- String restartableAttribute = element.getAttribute(RESTARTABLE_ATTRIBUTE);
- if (StringUtils.hasText(restartableAttribute)) {
- builder.addPropertyValue("restartable", restartableAttribute);
- }
-
- new PropertyParser(jobName, parserContext, BatchArtifactType.JOB).parseProperties(element);
-
- BeanDefinition flowDef = new FlowParser(jobName, jobName).parse(element, parserContext);
- builder.addPropertyValue("flow", flowDef);
-
- AbstractBeanDefinition stepContextBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(JsrStepContextFactoryBean.class)
- .getBeanDefinition();
-
- stepContextBeanDefinition.setScope("step");
-
- parserContext.getRegistry().registerBeanDefinition("stepContextFactory", stepContextBeanDefinition);
-
- new ListenerParser(JsrJobListenerFactoryBean.class, "jobExecutionListeners").parseListeners(element, parserContext, builder);
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespaceHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespaceHandler.java
deleted file mode 100644
index 61988a062..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespaceHandler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
-
-/**
- *
- * @author Michael Minella
- * @since 3.0
- */
-public class JsrNamespaceHandler extends NamespaceHandlerSupport {
-
- @Override
- public void init() {
- this.registerBeanDefinitionParser("job", new JsrJobParser());
- this.registerBeanDefinitionParser("batch-artifacts", new BatchParser());
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespacePostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespacePostProcessor.java
deleted file mode 100644
index 8a4038895..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespacePostProcessor.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import org.springframework.batch.core.repository.JobRepository;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-/**
- * @author Michael Minella
- */
-public class JsrNamespacePostProcessor implements BeanPostProcessor, ApplicationContextAware {
-
- private static final String DEFAULT_JOB_REPOSITORY_NAME = "jobRepository";
-
- private ApplicationContext applicationContext;
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
-
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- if(bean instanceof JobFactoryBean) {
- JobFactoryBean fb = (JobFactoryBean) bean;
- JobRepository jobRepository = fb.getJobRepository();
- if (jobRepository == null) {
- fb.setJobRepository((JobRepository) applicationContext.getBean(DEFAULT_JOB_REPOSITORY_NAME));
- }
- }
-
- return bean;
- }
-
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
-}
-
-
-
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespaceUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespaceUtils.java
deleted file mode 100644
index 3e29244ac..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrNamespaceUtils.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2013-2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor;
-import org.springframework.batch.core.jsr.configuration.support.JsrAutowiredAnnotationBeanPostProcessor;
-import org.springframework.batch.core.jsr.partition.support.JsrBeanScopeBeanFactoryPostProcessor;
-import org.springframework.batch.core.jsr.configuration.support.ThreadLocalClassloaderBeanPostProcessor;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.context.annotation.AnnotationConfigUtils;
-
-import java.util.HashMap;
-
-/**
- * Utility methods used in parsing of the JSR-352 batch namespace and related helpers.
- *
- * @author Michael Minella
- * @author Chris Schaefer
- * @since 3.0
- */
-class JsrNamespaceUtils {
- private static final String JOB_PROPERTIES_BEAN_NAME = "jobProperties";
- private static final String BATCH_PROPERTY_POST_PROCESSOR_BEAN_NAME = "batchPropertyPostProcessor";
- private static final String THREAD_LOCAL_CLASS_LOADER_BEAN_POST_PROCESSOR_BEAN_NAME = "threadLocalClassloaderBeanPostProcessor";
- private static final String BEAN_SCOPE_POST_PROCESSOR_BEAN_NAME = "beanScopeBeanPostProcessor";
- private static final String BATCH_PROPERTY_CONTEXT_BEAN_CLASS_NAME = "org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext";
- private static final String BATCH_PROPERTY_CONTEXT_BEAN_NAME = "batchPropertyContext";
- private static final String JSR_NAMESPACE_POST_PROCESSOR = "jsrNamespacePostProcessor";
-
- static void autoregisterJsrBeansForNamespace(ParserContext parserContext) {
- autoRegisterJobProperties(parserContext);
- autoRegisterBatchPostProcessor(parserContext);
- autoRegisterJsrAutowiredAnnotationBeanPostProcessor(parserContext);
- autoRegisterThreadLocalClassloaderBeanPostProcessor(parserContext);
- autoRegisterBeanScopeBeanFactoryPostProcessor(parserContext);
- autoRegisterBatchPropertyContext(parserContext);
- autoRegisterNamespacePostProcessor(parserContext);
- }
-
- private static void autoRegisterNamespacePostProcessor(ParserContext parserContext) {
- registerPostProcessor(parserContext, JsrNamespacePostProcessor.class, BeanDefinition.ROLE_INFRASTRUCTURE, JSR_NAMESPACE_POST_PROCESSOR);
- }
-
- private static void autoRegisterBeanScopeBeanFactoryPostProcessor(
- ParserContext parserContext) {
- registerPostProcessor(parserContext, JsrBeanScopeBeanFactoryPostProcessor.class, BeanDefinition.ROLE_INFRASTRUCTURE, BEAN_SCOPE_POST_PROCESSOR_BEAN_NAME);
- }
-
- private static void autoRegisterBatchPostProcessor(ParserContext parserContext) {
- registerPostProcessor(parserContext, BatchPropertyBeanPostProcessor.class, BeanDefinition.ROLE_INFRASTRUCTURE, BATCH_PROPERTY_POST_PROCESSOR_BEAN_NAME);
- }
-
- private static void autoRegisterJsrAutowiredAnnotationBeanPostProcessor(ParserContext parserContext) {
- registerPostProcessor(parserContext, JsrAutowiredAnnotationBeanPostProcessor.class, BeanDefinition.ROLE_INFRASTRUCTURE, AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
- }
-
- private static void autoRegisterThreadLocalClassloaderBeanPostProcessor(ParserContext parserContext) {
- registerPostProcessor(parserContext, ThreadLocalClassloaderBeanPostProcessor.class, BeanDefinition.ROLE_INFRASTRUCTURE, THREAD_LOCAL_CLASS_LOADER_BEAN_POST_PROCESSOR_BEAN_NAME);
- }
-
- private static void registerPostProcessor(ParserContext parserContext, Class> clazz, int role, String beanName) {
- BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
-
- AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
- beanDefinition.setRole(role);
-
- parserContext.getRegistry().registerBeanDefinition(beanName, beanDefinition);
- }
-
- // Registers a bean by the name of {@link #JOB_PROPERTIES_BEAN_NAME} so job level properties can be obtained through
- // for example a SPeL expression referencing #{jobProperties['key']} similar to systemProperties resolution.
- private static void autoRegisterJobProperties(ParserContext parserContext) {
- if (!parserContext.getRegistry().containsBeanDefinition(JOB_PROPERTIES_BEAN_NAME)) {
- AbstractBeanDefinition jobPropertiesBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(HashMap.class).getBeanDefinition();
- jobPropertiesBeanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-
- parserContext.getRegistry().registerBeanDefinition(JOB_PROPERTIES_BEAN_NAME, jobPropertiesBeanDefinition);
- }
- }
-
- private static void autoRegisterBatchPropertyContext(ParserContext parserContext) {
- if (!parserContext.getRegistry().containsBeanDefinition(BATCH_PROPERTY_CONTEXT_BEAN_NAME)) {
- AbstractBeanDefinition batchPropertyContextBeanDefinition =
- BeanDefinitionBuilder.genericBeanDefinition(BATCH_PROPERTY_CONTEXT_BEAN_CLASS_NAME)
- .getBeanDefinition();
-
- batchPropertyContextBeanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-
- parserContext.getRegistry().registerBeanDefinition(BATCH_PROPERTY_CONTEXT_BEAN_NAME, batchPropertyContextBeanDefinition);
- }
- }
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrSplitParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrSplitParser.java
deleted file mode 100644
index 62440141d..000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/JsrSplitParser.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.jsr.configuration.xml;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.springframework.beans.PropertyValue;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.ManagedList;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.core.task.SimpleAsyncTaskExecutor;
-import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
-
-/**
- * Parses a <split /> element as defined in JSR-352.
- *
- * @author Michael Minella
- * @author Chris Schaefer
- * @since 3.0
- */
-public class JsrSplitParser {
- private static final String TASK_EXECUTOR_PROPERTY_NAME = "taskExecutor";
- private static final String JSR_352_SPLIT_TASK_EXECUTOR_BEAN_NAME = "jsr352splitTaskExecutor";
-
- private String jobFactoryRef;
-
- public JsrSplitParser(String jobFactoryRef) {
- this.jobFactoryRef = jobFactoryRef;
- }
-
- public Collection parse(Element element, ParserContext parserContext) {
-
- String idAttribute = element.getAttribute("id");
-
- BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder
- .genericBeanDefinition("org.springframework.batch.core.jsr.job.flow.support.state.JsrSplitState");
-
- List flowElements = DomUtils.getChildElementsByTagName(element, "flow");
-
- if (flowElements.size() < 2) {
- parserContext.getReaderContext().error("A must contain at least two 'flow' elements.", element);
- }
-
- Collection