From a7f090a45d1aa055e3bdfbc4fdfd06d02ed6d0ac Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Mon, 2 Jun 2025 16:29:09 +0200 Subject: [PATCH] Make MapJobRegistry smart to auto register jobs at startup Before this commit, it was required to populate the job registry with a different component (like a bean post processor or a smart initializing singleton) before being able to use it with the JobOperator. This commit makes the `MapJobRegistry` smart enough to auto register jobs defined in the application context. This removes the need for a distinct component to populate the registry and therefore simplifies the configuration. This commit also: - removes the usage of `JobFactory` from `JobRegistry` - deprecates JobRegistrySmartInitializingSingleton and removes its configuration from the default batch configuration Resolves #4854 Resolves #4855 Resolves #4856 --- .../batch/core/configuration/JobRegistry.java | 9 ++- .../annotation/BatchRegistrar.java | 17 ----- .../support/DefaultBatchConfiguration.java | 17 ----- .../support/DefaultJobLoader.java | 6 +- .../JobFactoryRegistrationListener.java | 5 +- ...JobRegistrySmartInitializingSingleton.java | 8 +- .../configuration/support/MapJobRegistry.java | 65 ++++++++++------ .../annotation/BatchRegistrarTests.java | 11 --- .../DefaultBatchConfigurationTests.java | 16 +--- .../JobFactoryRegistrationListenerTests.java | 8 +- .../support/JobRegistryIntegrationTests.java | 3 +- ...gistrySmartInitializingSingletonTests.java | 28 +------ .../support/MapJobRegistryTests.java | 38 +++++----- .../TaskletStepAllowStartIfCompleteTests.java | 2 +- .../JobRegistryIntegrationTests-context.xml | 4 - ...text-with-smart-initializing-singleton.xml | 76 ------------------- .../xml/JobRegistryJobParserTests-context.xml | 4 - ...tStepAllowStartIfCompleteTests-context.xml | 4 - 18 files changed, 87 insertions(+), 234 deletions(-) delete mode 100644 spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context-with-smart-initializing-singleton.xml diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java index 86c4539fb..a2029dee4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2025 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. @@ -22,17 +22,18 @@ import org.springframework.batch.core.Job; * name. * * @author Dave Syer + * @author Mahmoud Ben Hassine * */ public interface JobRegistry extends ListableJobLocator { /** * Registers a {@link Job} at runtime. - * @param jobFactory the {@link Job} to be registered - * @throws DuplicateJobException if a factory with the same job name has already been + * @param job the {@link Job} to be registered + * @throws DuplicateJobException if a job with the same name has already been * registered. */ - void register(JobFactory jobFactory) throws DuplicateJobException; + void register(Job job) throws DuplicateJobException; /** * Unregisters a previously registered {@link Job}. If it was not previously diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java index fe836c8fa..3f4c36671 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java @@ -22,7 +22,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar; import org.springframework.batch.core.configuration.support.DefaultJobLoader; -import org.springframework.batch.core.configuration.support.JobRegistrySmartInitializingSingleton; import org.springframework.batch.core.configuration.support.MapJobRegistry; import org.springframework.batch.core.launch.support.JobOperatorFactoryBean; import org.springframework.batch.core.repository.support.JdbcJobRepositoryFactoryBean; @@ -70,7 +69,6 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { .synthesize(); registerJobRepository(registry, importingClassMetadata); registerJobRegistry(registry); - registerJobRegistrySmartInitializingSingleton(registry); registerJobOperator(registry, batchAnnotation); registerAutomaticJobRegistrar(registry, batchAnnotation); watch.stop(); @@ -220,21 +218,6 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { registry.registerBeanDefinition(JOB_REGISTRY, beanDefinition); } - private void registerJobRegistrySmartInitializingSingleton(BeanDefinitionRegistry registry) { - if (registry.containsBeanDefinition("jobRegistrySmartInitializingSingleton")) { - LOGGER - .info("Bean jobRegistrySmartInitializingSingleton already defined in the application context, skipping" - + " the registration of a jobRegistrySmartInitializingSingleton"); - return; - } - BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder - .genericBeanDefinition(JobRegistrySmartInitializingSingleton.class); - beanDefinitionBuilder.addPropertyReference(JOB_REGISTRY, JOB_REGISTRY); - - registry.registerBeanDefinition("jobRegistrySmartInitializingSingleton", - beanDefinitionBuilder.getBeanDefinition()); - } - private void registerJobOperator(BeanDefinitionRegistry registry, EnableBatchProcessing batchAnnotation) { if (registry.containsBeanDefinition(JOB_OPERATOR)) { LOGGER.info("Bean jobOperator already defined in the application context, skipping" diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java index cfaa0fa1d..81faf33ee 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java @@ -50,8 +50,6 @@ import org.springframework.transaction.annotation.Isolation; *
  • a {@link ResourcelessJobRepository} named "jobRepository"
  • *
  • a {@link MapJobRegistry} named "jobRegistry"
  • *
  • a {@link TaskExecutorJobOperator} named "JobOperator"
  • - *
  • a {@link JobRegistrySmartInitializingSingleton} named - * "jobRegistrySmartInitializingSingleton"
  • *
  • a {@link org.springframework.batch.core.scope.StepScope} named "stepScope"
  • *
  • a {@link org.springframework.batch.core.scope.JobScope} named "jobScope"
  • * @@ -117,21 +115,6 @@ public class DefaultBatchConfiguration implements ApplicationContextAware { } } - @Bean - public JobRegistrySmartInitializingSingleton jobRegistrySmartInitializingSingleton(JobRegistry jobRegistry) - throws BatchConfigurationException { - JobRegistrySmartInitializingSingleton jobRegistrySmartInitializingSingleton = new JobRegistrySmartInitializingSingleton(); - jobRegistrySmartInitializingSingleton.setJobRegistry(jobRegistry); - try { - jobRegistrySmartInitializingSingleton.afterPropertiesSet(); - return jobRegistrySmartInitializingSingleton; - } - catch (Exception e) { - throw new BatchConfigurationException( - "Unable to configure the default job registry SmartInitializingSingleton", e); - } - } - /** * Return the transaction manager to use for the job operator. Defaults to * {@link ResourcelessTransactionManager}. diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java index 4dde8ea15..eb6929d31 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 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. @@ -27,7 +27,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.DuplicateJobException; -import org.springframework.batch.core.configuration.JobFactory; import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.configuration.StepRegistry; import org.springframework.batch.core.launch.NoSuchJobException; @@ -251,8 +250,7 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { * @throws DuplicateJobException if that job is already registered */ private void doRegister(ConfigurableApplicationContext context, Job job) throws DuplicateJobException { - final JobFactory jobFactory = new ReferenceJobFactory(job); - jobRegistry.register(jobFactory); + jobRegistry.register(job); if (stepRegistry != null) { if (!(job instanceof StepLocator)) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java index 3ed14c297..2a2525068 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 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. @@ -27,6 +27,7 @@ import org.springframework.batch.core.configuration.JobRegistry; * Generic service that can bind and unbind a {@link JobFactory} in a {@link JobRegistry}. * * @author Dave Syer + * @author Mahmoud Ben Hassine * */ public class JobFactoryRegistrationListener { @@ -53,7 +54,7 @@ public class JobFactoryRegistrationListener { if (logger.isInfoEnabled()) { logger.info("Binding JobFactory: " + jobFactory.getJobName()); } - jobRegistry.register(jobFactory); + jobRegistry.register(jobFactory.createJob()); } /** diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java index bd6f5b9a4..985c8859f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java @@ -45,7 +45,10 @@ import org.springframework.util.Assert; * * @author Henning Pƶttker * @since 5.1.1 + * @deprecated since 6.0 with no replacement. Register a {@link MapJobRegistry} as a bean, + * and it will automatically register all {@link Job} beans in the application context. */ +@Deprecated(since = "6.0", forRemoval = true) public class JobRegistrySmartInitializingSingleton implements SmartInitializingSingleton, BeanFactoryAware, InitializingBean, DisposableBean { @@ -143,12 +146,11 @@ public class JobRegistrySmartInitializingSingleton groupName = getGroupName(defaultListableBeanFactory.getBeanDefinition(beanName), job); } job = groupName == null ? job : new GroupAwareJob(groupName, job); - ReferenceJobFactory jobFactory = new ReferenceJobFactory(job); - String name = jobFactory.getJobName(); + String name = job.getName(); if (logger.isDebugEnabled()) { logger.debug("Registering job: " + name); } - jobRegistry.register(jobFactory); + jobRegistry.register(job); jobNames.add(name); } catch (DuplicateJobException e) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java index 3e55bedc0..2ab6f3989 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2019 the original author or authors. + * Copyright 2006-2025 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. @@ -16,68 +16,89 @@ package org.springframework.batch.core.configuration.support; import java.util.Collections; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.Job; import org.springframework.batch.core.configuration.DuplicateJobException; -import org.springframework.batch.core.configuration.JobFactory; import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.launch.NoSuchJobException; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Simple, thread-safe, map-based implementation of {@link JobRegistry}. + * Simple, thread-safe, map-based implementation of {@link JobRegistry}. This registry is + * a {@link SmartInitializingSingleton} that is automatically populated with all + * {@link Job} beans in the {@link ApplicationContext}. * * @author Dave Syer * @author Robert Fischer * @author Mahmoud Ben Hassine */ -public class MapJobRegistry implements JobRegistry { +public class MapJobRegistry implements JobRegistry, SmartInitializingSingleton, ApplicationContextAware { + + protected final Log logger = LogFactory.getLog(getClass()); /** - * The map holding the registered job factories. + * The map holding the registered jobs. */ - // The "final" ensures that it is visible and initialized when the constructor - // resolves. - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final ConcurrentMap map = new ConcurrentHashMap<>(); + + private ApplicationContext applicationContext; @Override - public void register(JobFactory jobFactory) throws DuplicateJobException { - Assert.notNull(jobFactory, "jobFactory is null"); - String name = jobFactory.getJobName(); - Assert.notNull(name, "Job configuration must have a name."); - JobFactory previousValue = map.putIfAbsent(name, jobFactory); + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + public void afterSingletonsInstantiated() { + Map jobBeans = this.applicationContext.getBeansOfType(Job.class); + this.map.putAll(jobBeans); + } + + @Override + public void register(Job job) throws DuplicateJobException { + Assert.notNull(job, "job must not be null"); + String jobName = job.getName(); + Assert.notNull(jobName, "Job name must not be null"); + Job previousValue = this.map.putIfAbsent(jobName, job); if (previousValue != null) { - throw new DuplicateJobException("A job configuration with this name [" + name + "] was already registered"); + throw new DuplicateJobException("A job with this name [" + jobName + "] was already registered"); } } @Override public void unregister(String name) { - Assert.notNull(name, "Job configuration must have a name."); - map.remove(name); + Assert.notNull(name, "Job name must not be null"); + this.map.remove(name); } @Override public Job getJob(@Nullable String name) throws NoSuchJobException { - JobFactory factory = map.get(name); - if (factory == null) { - throw new NoSuchJobException("No job configuration with the name [" + name + "] was registered"); + Job job = this.map.get(name); + if (job == null) { + throw new NoSuchJobException("No job with the name [" + name + "] was registered"); } else { - return factory.createJob(); + return job; } } /** - * Provides an unmodifiable view of the job names. + * Provides an unmodifiable view of job names. */ @Override public Set getJobNames() { - return Collections.unmodifiableSet(map.keySet()); + return Collections.unmodifiableSet(this.map.keySet()); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java index 453ca766c..1cdbbca2c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java @@ -27,7 +27,6 @@ import org.springframework.aop.framework.Advised; import org.springframework.batch.core.DefaultJobKeyGenerator; import org.springframework.batch.core.JobKeyGenerator; import org.springframework.batch.core.configuration.JobRegistry; -import org.springframework.batch.core.configuration.support.JobRegistrySmartInitializingSingleton; import org.springframework.batch.core.converter.DefaultJobParametersConverter; import org.springframework.batch.core.converter.JobParametersConverter; import org.springframework.batch.core.converter.JsonJobParametersConverter; @@ -64,8 +63,6 @@ class BatchRegistrarTests { Assertions.assertTrue(Mockito.mockingDetails(context.getBean(JobRepository.class)).isMock()); Assertions.assertTrue(Mockito.mockingDetails(context.getBean(JobRegistry.class)).isMock()); Assertions.assertTrue(Mockito.mockingDetails(context.getBean(JobOperator.class)).isMock()); - Assertions - .assertTrue(Mockito.mockingDetails(context.getBean(JobRegistrySmartInitializingSingleton.class)).isMock()); } @Test @@ -147,15 +144,12 @@ class BatchRegistrarTests { JobRepository jobRepository = context.getBean(JobRepository.class); JobRegistry jobRegistry = context.getBean(JobRegistry.class); JobOperator jobOperator = context.getBean(JobOperator.class); - JobRegistrySmartInitializingSingleton jobRegistrySmartInitializingSingleton = context - .getBean(JobRegistrySmartInitializingSingleton.class); // then Assertions.assertNotNull(jobLauncher); Assertions.assertNotNull(jobRepository); Assertions.assertNotNull(jobRegistry); Assertions.assertNotNull(jobOperator); - Assertions.assertNotNull(jobRegistrySmartInitializingSingleton); } @Test @@ -236,11 +230,6 @@ class BatchRegistrarTests { return Mockito.mock(); } - @Bean - public JobRegistrySmartInitializingSingleton jobRegistrySmartInitializingSingleton() { - return Mockito.mock(); - } - } @Configuration diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java index 39d773fbc..9a03214b1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the original author or authors. + * Copyright 2022-2025 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. @@ -36,7 +36,6 @@ import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -72,9 +71,6 @@ class DefaultBatchConfigurationTests { Assertions.assertEquals(1, jobRepositories.size()); JobRepository jobRepository = jobRepositories.entrySet().iterator().next().getValue(); Assertions.assertInstanceOf(DummyJobRepository.class, jobRepository); - Map jobRegistrySmartInitializingSingletonMap = context - .getBeansOfType(JobRegistrySmartInitializingSingleton.class); - Assertions.assertEquals(1, jobRegistrySmartInitializingSingletonMap.size()); } @Test @@ -87,15 +83,12 @@ class DefaultBatchConfigurationTests { JobRepository jobRepository = context.getBean(JobRepository.class); JobRegistry jobRegistry = context.getBean(JobRegistry.class); JobOperator jobOperator = context.getBean(JobOperator.class); - JobRegistrySmartInitializingSingleton jobRegistrySmartInitializingSingleton = context - .getBean(JobRegistrySmartInitializingSingleton.class); // then Assertions.assertNotNull(jobLauncher); Assertions.assertNotNull(jobRepository); Assertions.assertNotNull(jobRegistry); Assertions.assertNotNull(jobOperator); - Assertions.assertNotNull(jobRegistrySmartInitializingSingleton); } @Configuration @@ -136,13 +129,6 @@ class DefaultBatchConfigurationTests { return new DummyJobRepository(); } - @Bean - public JobRegistrySmartInitializingSingleton jobRegistrySmartInitializingSingleton(JobRegistry jobRegistry) { - JobRegistrySmartInitializingSingleton smartInitializingSingleton = new JobRegistrySmartInitializingSingleton(); - smartInitializingSingleton.setJobRegistry(jobRegistry); - return smartInitializingSingleton; - } - } } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListenerTests.java index d834a3e98..d71fb9862 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2025 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. @@ -20,9 +20,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.springframework.batch.core.Job; import org.springframework.batch.core.configuration.JobFactory; +import org.springframework.batch.core.test.repository.JobSupport; /** * @author Dave Syer + * @author Mahmoud Ben Hassine * */ class JobFactoryRegistrationListenerTests { @@ -37,7 +39,7 @@ class JobFactoryRegistrationListenerTests { listener.bind(new JobFactory() { @Override public Job createJob() { - return null; + return new JobSupport("foo"); } @Override @@ -54,7 +56,7 @@ class JobFactoryRegistrationListenerTests { listener.unbind(new JobFactory() { @Override public Job createJob() { - return null; + return new JobSupport("foo"); } @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java index 7586b62eb..7170e64b4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2025 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. @@ -25,6 +25,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; /** * @author Dave Syer + * @author Mahmoud Ben Hassine * */ @SpringJUnitConfig diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingletonTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingletonTests.java index f6db1e018..dd2a14f8d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingletonTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingletonTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 the original author or authors. + * Copyright 2024-2025 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. @@ -26,11 +26,9 @@ import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.job.JobSupport; import org.springframework.beans.FatalBeanException; import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.context.support.ClassPathXmlApplicationContext; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.lenient; @@ -95,28 +93,4 @@ class JobRegistrySmartInitializingSingletonTests { assertTrue(jobRegistry.getJobNames().isEmpty()); } - @Test - void testExecutionWithApplicationContext() throws Exception { - var context = new ClassPathXmlApplicationContext("test-context-with-smart-initializing-singleton.xml", - getClass()); - var registry = context.getBean("registry", JobRegistry.class); - Collection jobNames = registry.getJobNames(); - String[] names = context.getBeanNamesForType(JobSupport.class); - int count = names.length; - // Each concrete bean of type JobConfiguration is registered... - assertEquals(count, jobNames.size()); - // N.B. there is a failure / wonky mode where a parent bean is given an - // explicit name or beanName (using property setter): in this case then - // child beans will have the same name and will be re-registered (and - // override, if the registry supports that). - assertNotNull(registry.getJob("test-job")); - assertEquals(context.getBean("test-job-with-name"), registry.getJob("foo")); - assertEquals(context.getBean("test-job-with-bean-name"), registry.getJob("bar")); - assertEquals(context.getBean("test-job-with-parent-and-name"), registry.getJob("spam")); - assertEquals(context.getBean("test-job-with-parent-and-bean-name"), registry.getJob("bucket")); - assertEquals(context.getBean("test-job-with-concrete-parent"), registry.getJob("maps")); - assertEquals(context.getBean("test-job-with-concrete-parent-and-name"), registry.getJob("oof")); - assertEquals(context.getBean("test-job-with-concrete-parent-and-bean-name"), registry.getJob("rab")); - } - } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java index d35c5ff7d..db7d32253 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2025 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. @@ -15,21 +15,19 @@ */ package org.springframework.batch.core.configuration.support; -import java.util.Collection; - import org.junit.jupiter.api.Test; +import org.springframework.batch.core.Job; import org.springframework.batch.core.configuration.DuplicateJobException; -import org.springframework.batch.core.configuration.JobFactory; import org.springframework.batch.core.job.JobSupport; import org.springframework.batch.core.launch.NoSuchJobException; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.*; /** * @author Dave Syer + * @author Mahmoud Ben Hassine * */ class MapJobRegistryTests { @@ -38,7 +36,7 @@ class MapJobRegistryTests { @Test void testUnregister() throws Exception { - registry.register(new ReferenceJobFactory(new JobSupport("foo"))); + registry.register(new JobSupport("foo")); assertNotNull(registry.getJob("foo")); registry.unregister("foo"); Exception exception = assertThrows(NoSuchJobException.class, () -> registry.getJob("foo")); @@ -47,28 +45,30 @@ class MapJobRegistryTests { @Test void testReplaceDuplicateConfiguration() throws Exception { - registry.register(new ReferenceJobFactory(new JobSupport("foo"))); - JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); - Exception exception = assertThrows(DuplicateJobException.class, () -> registry.register(jobFactory)); + registry.register(new JobSupport("foo")); + Job job = new JobSupport("foo"); + Exception exception = assertThrows(DuplicateJobException.class, () -> registry.register(job)); assertTrue(exception.getMessage().contains("foo")); } @Test void testRealDuplicateConfiguration() throws Exception { - JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); - registry.register(jobFactory); - Exception exception = assertThrows(DuplicateJobException.class, () -> registry.register(jobFactory)); + Job job = new JobSupport("foo"); + registry.register(job); + Exception exception = assertThrows(DuplicateJobException.class, () -> registry.register(job)); assertTrue(exception.getMessage().contains("foo")); } @Test void testGetJobConfigurations() throws Exception { - JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); - registry.register(jobFactory); - registry.register(new ReferenceJobFactory(new JobSupport("bar"))); + Job job1 = new JobSupport("foo"); + Job job2 = new JobSupport("bar"); + registry.register(job1); + registry.register(job2); Collection configurations = registry.getJobNames(); assertEquals(2, configurations.size()); - assertTrue(configurations.contains(jobFactory.getJobName())); + assertTrue(configurations.contains(job1.getName())); + assertTrue(configurations.contains(job2.getName())); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java index 11823defd..a2cfc4341 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 the original author or authors. + * Copyright 2013-2025 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. diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml index 616446dd4..8dff8d97d 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml @@ -13,10 +13,6 @@ - - - - diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context-with-smart-initializing-singleton.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context-with-smart-initializing-singleton.xml deleted file mode 100644 index 64ae6eed6..000000000 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context-with-smart-initializing-singleton.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml index 240e5baa2..5af850502 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml @@ -19,10 +19,6 @@ - - - diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml index c122971d1..ffcebb51e 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml @@ -38,8 +38,4 @@ - - - -