This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 7ee0f7f4e4 FINERACT-2421: Improved Spring Batch context handling
7ee0f7f4e4 is described below

commit 7ee0f7f4e40a56be06d188c0928e44afd33eb1b0
Author: Adam Saghy <[email protected]>
AuthorDate: Thu Dec 18 18:07:28 2025 +0100

    FINERACT-2421: Improved Spring Batch context handling
---
 .../fineract/cob/loan/ApplyLoanLockTasklet.java    |  9 ++--
 .../apache/fineract/cob/loan/LoanCOBConstant.java  |  1 +
 .../cob/loan/LoanCOBManagerConfiguration.java      | 27 +++++-------
 .../fineract/cob/loan/LoanCOBPartitioner.java      | 50 ++++++++++------------
 .../cob/loan/LoanCOBWorkerConfiguration.java       | 29 ++++++-------
 .../apache/fineract/cob/loan/LoanItemReader.java   | 16 +++----
 .../fineract/cob/loan/LoanLockingServiceImpl.java  | 17 --------
 .../cob/resolver/BusinessDateResolver.java         | 39 +++++++++++++++++
 .../CatchUpFlagResolver.java}                      | 28 ++++++------
 .../springbatch/InputChannelInterceptor.java       | 10 +++--
 .../jms/JmsBatchWorkerMessageListener.java         |  2 +
 .../kafka/KafkaRemoteMessageListener.java          |  2 +
 .../loan/ApplyLoanLockTaskletStepDefinitions.java  | 10 ++---
 .../fineract/cob/loan/LoanCOBPartitionerTest.java  | 49 ++++++++++++---------
 .../cob/loan/LoanItemReaderStepDefinitions.java    |  3 +-
 .../fineract/cob/loan/LoanItemReaderTest.java      | 27 ++++++------
 16 files changed, 166 insertions(+), 153 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java
index 3d6a90793c..b8eda2d144 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java
@@ -28,12 +28,12 @@ import java.util.List;
 import java.util.Objects;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.fineract.cob.common.CustomJobParameterResolver;
 import org.apache.fineract.cob.converter.COBParameterConverter;
 import org.apache.fineract.cob.data.COBParameter;
 import org.apache.fineract.cob.domain.LoanAccountLock;
 import org.apache.fineract.cob.domain.LockOwner;
 import org.apache.fineract.cob.exceptions.LoanLockCannotBeAppliedException;
+import org.apache.fineract.cob.resolver.CatchUpFlagResolver;
 import org.apache.fineract.infrastructure.core.config.FineractProperties;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.scope.context.ChunkContext;
@@ -53,7 +53,6 @@ public class ApplyLoanLockTasklet implements Tasklet {
     private final FineractProperties fineractProperties;
     private final LoanLockingService loanLockingService;
     private final RetrieveLoanIdService retrieveLoanIdService;
-    private final CustomJobParameterResolver customJobParameterResolver;
     private final TransactionTemplate transactionTemplate;
 
     @Override
@@ -63,6 +62,7 @@ public class ApplyLoanLockTasklet implements Tasklet {
         ExecutionContext executionContext = 
contribution.getStepExecution().getExecutionContext();
         long numberOfExecutions = 
contribution.getStepExecution().getCommitCount();
         COBParameter loanCOBParameter = 
COBParameterConverter.convert(executionContext.get(LoanCOBConstant.LOAN_COB_PARAMETER));
+        boolean isCatchUp = 
CatchUpFlagResolver.resolve(contribution.getStepExecution());
         List<Long> loanIds;
         if (Objects.isNull(loanCOBParameter)
                 || (Objects.isNull(loanCOBParameter.getMinAccountId()) && 
Objects.isNull(loanCOBParameter.getMaxAccountId()))
@@ -70,10 +70,7 @@ public class ApplyLoanLockTasklet implements Tasklet {
             loanIds = Collections.emptyList();
         } else {
             loanIds = new ArrayList<>(
-                    
retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter,
-                            customJobParameterResolver
-                                    
.getCustomJobParameterById(contribution.getStepExecution(), 
LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME)
-                                    
.map(Boolean::parseBoolean).orElse(false)));
+                    
retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter,
 isCatchUp));
         }
         List<List<Long>> loanIdPartitions = Lists.partition(loanIds, 
getInClauseParameterSizeLimit());
         List<LoanAccountLock> accountLocks = new ArrayList<>();
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
index 9916ffea78..ad21d3fcf9 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
@@ -32,6 +32,7 @@ public final class LoanCOBConstant extends COBConstant {
     public static final String LOAN_IDS_PARAMETER_NAME = "LoanIds";
 
     public static final String LOAN_COB_PARTITIONER_STEP = "Loan COB partition 
- Step";
+    public static final String PARTITION_KEY = "partition";
 
     private LoanCOBConstant() {
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
index 4cbbd6df0c..61b08ba21b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
@@ -20,20 +20,17 @@ package org.apache.fineract.cob.loan;
 
 import static org.apache.fineract.cob.loan.LoanCOBConstant.JOB_NAME;
 
-import java.util.List;
 import org.apache.fineract.cob.COBBusinessStepService;
 import org.apache.fineract.cob.common.CustomJobParameterResolver;
 import org.apache.fineract.cob.conditions.BatchManagerCondition;
 import org.apache.fineract.cob.listener.COBExecutionListenerRunner;
-import org.apache.fineract.cob.listener.JobExecutionContextCopyListener;
 import 
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
 import org.apache.fineract.infrastructure.jobs.service.JobName;
 import org.apache.fineract.infrastructure.springbatch.PropertyService;
 import org.springframework.batch.core.Job;
 import org.springframework.batch.core.Step;
-import org.springframework.batch.core.configuration.annotation.JobScope;
+import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.core.configuration.annotation.StepScope;
-import org.springframework.batch.core.explore.JobExplorer;
 import org.springframework.batch.core.job.builder.JobBuilder;
 import org.springframework.batch.core.launch.JobOperator;
 import org.springframework.batch.core.launch.support.RunIdIncrementer;
@@ -43,6 +40,7 @@ import 
org.springframework.batch.core.step.builder.StepBuilder;
 import 
org.springframework.batch.integration.config.annotation.EnableBatchIntegration;
 import 
org.springframework.batch.integration.partition.RemotePartitioningManagerStepBuilderFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Conditional;
@@ -70,8 +68,6 @@ public class LoanCOBManagerConfiguration {
     @Autowired
     private JobOperator jobOperator;
     @Autowired
-    private JobExplorer jobExplorer;
-    @Autowired
     private ApplicationContext applicationContext;
     @Autowired
     private RetrieveLoanIdService retrieveLoanIdService;
@@ -82,17 +78,16 @@ public class LoanCOBManagerConfiguration {
 
     @Bean
     @StepScope
-    public LoanCOBPartitioner partitioner() {
-        return new LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator, jobExplorer,
+    public LoanCOBPartitioner partitioner(@Value("#{stepExecution}") 
StepExecution stepExecution) {
+        return new LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator, stepExecution,
                 LoanCOBConstant.NUMBER_OF_DAYS_BEHIND);
     }
 
-    @Bean
-    public Step loanCOBStep() {
+    @Bean("loanCOBStep")
+    public Step loanCOBStep(LoanCOBPartitioner partitioner) {
         return 
stepBuilderFactory.get(LoanCOBConstant.LOAN_COB_PARTITIONER_STEP)
-                .partitioner(LoanCOBConstant.LOAN_COB_WORKER_STEP, 
partitioner()).pollInterval(propertyService.getPollInterval(JOB_NAME))
-                .listener(new 
JobExecutionContextCopyListener(List.of("BusinessDate", 
"IS_CATCH_UP"))).outputChannel(outboundRequests)
-                .build();
+                .partitioner(LoanCOBConstant.LOAN_COB_WORKER_STEP, 
partitioner).pollInterval(propertyService.getPollInterval(JOB_NAME))
+                .outputChannel(outboundRequests).build();
     }
 
     @Bean
@@ -108,23 +103,21 @@ public class LoanCOBManagerConfiguration {
     }
 
     @Bean
-    @JobScope
     public ResolveLoanCOBCustomJobParametersTasklet 
resolveCustomJobParametersTasklet() {
         return new 
ResolveLoanCOBCustomJobParametersTasklet(customJobParameterResolver);
     }
 
     @Bean
-    @JobScope
     public StayedLockedLoansTasklet stayedLockedTasklet() {
         return new StayedLockedLoansTasklet(businessEventNotifierService, 
retrieveLoanIdService);
     }
 
     @Bean(name = "loanCOBJob")
-    public Job loanCOBJob() {
+    public Job loanCOBJob(LoanCOBPartitioner partitioner) {
         return new JobBuilder(JobName.LOAN_COB.name(), jobRepository) //
                 .listener(new COBExecutionListenerRunner(applicationContext, 
JobName.LOAN_COB.name())) //
                 .start(resolveCustomJobParametersStep()) //
-                .next(loanCOBStep()).next(stayedLockedStep()) //
+                .next(loanCOBStep(partitioner)).next(stayedLockedStep()) //
                 .incrementer(new RunIdIncrementer()) //
                 .build();
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java
index 69bb2c8bec..b3cfdbc65d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBPartitioner.java
@@ -25,22 +25,20 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
-import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.cob.COBBusinessStepService;
 import org.apache.fineract.cob.data.BusinessStepNameAndOrder;
 import org.apache.fineract.cob.data.COBParameter;
 import org.apache.fineract.cob.data.COBPartition;
-import org.apache.fineract.infrastructure.jobs.service.JobName;
+import org.apache.fineract.cob.resolver.BusinessDateResolver;
+import org.apache.fineract.cob.resolver.CatchUpFlagResolver;
 import org.apache.fineract.infrastructure.springbatch.PropertyService;
-import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.explore.JobExplorer;
+import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.core.launch.JobExecutionNotRunningException;
 import org.springframework.batch.core.launch.JobOperator;
 import org.springframework.batch.core.launch.NoSuchJobExecutionException;
 import org.springframework.batch.core.partition.support.Partitioner;
 import org.springframework.batch.item.ExecutionContext;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.lang.NonNull;
 import org.springframework.util.StopWatch;
 
@@ -54,17 +52,9 @@ public class LoanCOBPartitioner implements Partitioner {
     private final COBBusinessStepService cobBusinessStepService;
     private final RetrieveLoanIdService retrieveLoanIdService;
     private final JobOperator jobOperator;
-    private final JobExplorer jobExplorer;
-
+    private final StepExecution stepExecution;
     private final Long numberOfDays;
 
-    @Value("#{stepExecutionContext['BusinessDate']}")
-    @Setter
-    private LocalDate businessDate;
-    @Value("#{stepExecutionContext['IS_CATCH_UP']}")
-    @Setter
-    private Boolean isCatchUp;
-
     @NonNull
     @Override
     public Map<String, ExecutionContext> partition(int gridSize) {
@@ -79,45 +69,49 @@ public class LoanCOBPartitioner implements Partitioner {
             stopJobExecution();
             return Map.of();
         }
+        LocalDate businessDate = BusinessDateResolver.resolve(stepExecution);
+        boolean isCatchUp = CatchUpFlagResolver.resolve(stepExecution);
         StopWatch sw = new StopWatch();
         sw.start();
         List<COBPartition> loanCOBPartitions = new ArrayList<>(
-                retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays, 
businessDate, isCatchUp != null && isCatchUp, partitionSize));
+                retrieveLoanIdService.retrieveLoanCOBPartitions(numberOfDays, 
businessDate, isCatchUp, partitionSize));
         sw.stop();
         // if there is no loan to be closed, we still would like to create at 
least one partition
 
-        if (loanCOBPartitions.size() == 0) {
+        if (loanCOBPartitions.isEmpty()) {
             loanCOBPartitions.add(new COBPartition(0L, 0L, 1L, 0L));
         }
         log.info(
                 "LoanCOBPartitioner found {} loans to be processed as part of 
COB. {} partitions were created using partition size {}. 
RetrieveLoanCOBPartitions was executed in {} ms.",
                 getLoanCount(loanCOBPartitions), loanCOBPartitions.size(), 
partitionSize, sw.getTotalTimeMillis());
-        return loanCOBPartitions.stream()
-                .collect(Collectors.toMap(l -> PARTITION_PREFIX + 
l.getPageNo(), l -> createNewPartition(cobBusinessSteps, l)));
+        return loanCOBPartitions.stream().collect(Collectors.toMap(l -> 
PARTITION_PREFIX + l.getPageNo(),
+                l -> createNewPartition(cobBusinessSteps, l, businessDate, 
isCatchUp)));
     }
 
     private long getLoanCount(List<COBPartition> loanCOBPartitions) {
         return 
loanCOBPartitions.stream().map(COBPartition::getCount).reduce(0L, Long::sum);
     }
 
-    private ExecutionContext createNewPartition(Set<BusinessStepNameAndOrder> 
cobBusinessSteps, COBPartition loanCOBPartition) {
+    private ExecutionContext createNewPartition(Set<BusinessStepNameAndOrder> 
cobBusinessSteps, COBPartition loanCOBPartition,
+            LocalDate businessDate, boolean isCatchUp) {
         ExecutionContext executionContext = new ExecutionContext();
         executionContext.put(LoanCOBConstant.BUSINESS_STEPS, cobBusinessSteps);
         executionContext.put(LoanCOBConstant.LOAN_COB_PARAMETER,
                 new COBParameter(loanCOBPartition.getMinId(), 
loanCOBPartition.getMaxId()));
-        executionContext.put("partition", PARTITION_PREFIX + 
loanCOBPartition.getPageNo());
+        executionContext.put(LoanCOBConstant.PARTITION_KEY, PARTITION_PREFIX + 
loanCOBPartition.getPageNo());
+        executionContext.put(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME, 
businessDate.toString());
+        executionContext.put(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME, 
Boolean.toString(isCatchUp));
         return executionContext;
     }
 
     private void stopJobExecution() {
-        Set<JobExecution> runningJobExecutions = 
jobExplorer.findRunningJobExecutions(JobName.LOAN_COB.name());
-        for (JobExecution jobExecution : runningJobExecutions) {
-            try {
-                jobOperator.stop(jobExecution.getId());
-            } catch (NoSuchJobExecutionException | 
JobExecutionNotRunningException e) {
-                log.error("There is no running execution for the given 
execution ID. Execution ID: {}", jobExecution.getId());
-                throw new RuntimeException(e);
-            }
+        Long jobId = stepExecution.getJobExecution().getId();
+        try {
+            jobOperator.stop(jobId);
+        } catch (NoSuchJobExecutionException | JobExecutionNotRunningException 
e) {
+            log.error("There is no running execution for the given execution 
ID. Execution ID: {}", jobId);
+            throw new RuntimeException(e);
         }
+
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java
index f50987afad..f2e9bc4303 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java
@@ -19,7 +19,6 @@
 package org.apache.fineract.cob.loan;
 
 import org.apache.fineract.cob.COBBusinessStepService;
-import org.apache.fineract.cob.common.CustomJobParameterResolver;
 import org.apache.fineract.cob.common.InitialisationTasklet;
 import org.apache.fineract.cob.common.ResetContextTasklet;
 import org.apache.fineract.cob.conditions.BatchWorkerCondition;
@@ -81,21 +80,18 @@ public class LoanCOBWorkerConfiguration {
     @Autowired
     private LoanLockingService loanLockingService;
 
-    @Autowired
-    private CustomJobParameterResolver customJobParameterResolver;
-
     @Bean(name = LoanCOBConstant.LOAN_COB_WORKER_STEP)
-    public Step loanCOBWorkerStep() {
-        return stepBuilderFactory.get("Loan COB worker - 
Step").inputChannel(inboundRequests).flow(flow()).build();
+    public Step loanCOBWorkerStep(Flow cobFlow) {
+        return stepBuilderFactory.get("Loan COB worker - 
Step").inputChannel(inboundRequests).flow(cobFlow).build();
     }
 
-    @Bean
-    public Flow flow() {
-        return new 
FlowBuilder<Flow>("cobFlow").start(initialisationStep(null)).next(applyLockStep(null)).next(loanBusinessStep(null,
 null))
-                .next(resetContextStep(null)).build();
+    @Bean("cobFlow")
+    public Flow flow(Step initialisationStep, Step applyLockStep, Step 
loanBusinessStep, Step resetContextStep) {
+        return new 
FlowBuilder<Flow>("cobFlow").start(initialisationStep).next(applyLockStep).next(loanBusinessStep).next(resetContextStep)
+                .build();
     }
 
-    @Bean
+    @Bean("initialisationStep")
     @StepScope
     public Step 
initialisationStep(@Value("#{stepExecutionContext['partition']}") String 
partitionName) {
         return new StepBuilder("Initialisation - Step:" + partitionName, 
jobRepository).tasklet(initialiseContext(), transactionManager)
@@ -118,7 +114,7 @@ public class LoanCOBWorkerConfiguration {
         return taskExecutor;
     }
 
-    @Bean
+    @Bean("loanBusinessStep")
     @StepScope
     public Step 
loanBusinessStep(@Value("#{stepExecutionContext['partition']}") String 
partitionName, TaskExecutor cobTaskExecutor) {
         SimpleStepBuilder<Loan, Loan> stepBuilder = new StepBuilder("Loan 
Business - Step:" + partitionName, jobRepository)
@@ -141,13 +137,13 @@ public class LoanCOBWorkerConfiguration {
         return stepBuilder.build();
     }
 
-    @Bean
+    @Bean("applyLockStep")
     @StepScope
     public Step applyLockStep(@Value("#{stepExecutionContext['partition']}") 
String partitionName) {
         return new StepBuilder("Apply lock - Step:" + partitionName, 
jobRepository).tasklet(applyLock(), transactionManager).build();
     }
 
-    @Bean
+    @Bean("resetContextStep")
     @StepScope
     public Step 
resetContextStep(@Value("#{stepExecutionContext['partition']}") String 
partitionName) {
         return new StepBuilder("Reset context - Step:" + partitionName, 
jobRepository).tasklet(resetContext(), transactionManager).build();
@@ -165,8 +161,7 @@ public class LoanCOBWorkerConfiguration {
 
     @Bean
     public ApplyLoanLockTasklet applyLock() {
-        return new ApplyLoanLockTasklet(fineractProperties, 
loanLockingService, retrieveLoanIdService, customJobParameterResolver,
-                transactionTemplate);
+        return new ApplyLoanLockTasklet(fineractProperties, 
loanLockingService, retrieveLoanIdService, transactionTemplate);
     }
 
     @Bean
@@ -177,7 +172,7 @@ public class LoanCOBWorkerConfiguration {
     @Bean
     @StepScope
     public LoanItemReader cobWorkerItemReader() {
-        return new LoanItemReader(loanRepository, retrieveLoanIdService, 
customJobParameterResolver, loanLockingService);
+        return new LoanItemReader(loanRepository, retrieveLoanIdService, 
loanLockingService);
     }
 
     @Bean
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java
index 9ee7d325de..f6c52f2df1 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java
@@ -24,11 +24,11 @@ import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.LinkedBlockingQueue;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.fineract.cob.common.CustomJobParameterResolver;
 import org.apache.fineract.cob.converter.COBParameterConverter;
 import org.apache.fineract.cob.data.COBParameter;
 import org.apache.fineract.cob.domain.LoanAccountLock;
 import org.apache.fineract.cob.domain.LockOwner;
+import org.apache.fineract.cob.resolver.CatchUpFlagResolver;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
 import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.core.annotation.BeforeStep;
@@ -39,14 +39,12 @@ import org.springframework.lang.NonNull;
 public class LoanItemReader extends AbstractLoanItemReader {
 
     private final RetrieveLoanIdService retrieveLoanIdService;
-    private final CustomJobParameterResolver customJobParameterResolver;
     private final LoanLockingService loanLockingService;
 
     public LoanItemReader(LoanRepository loanRepository, RetrieveLoanIdService 
retrieveLoanIdService,
-            CustomJobParameterResolver customJobParameterResolver, 
LoanLockingService loanLockingService) {
+            LoanLockingService loanLockingService) {
         super(loanRepository);
         this.retrieveLoanIdService = retrieveLoanIdService;
-        this.customJobParameterResolver = customJobParameterResolver;
         this.loanLockingService = loanLockingService;
     }
 
@@ -56,15 +54,15 @@ public class LoanItemReader extends AbstractLoanItemReader {
         ExecutionContext executionContext = 
stepExecution.getExecutionContext();
         COBParameter loanCOBParameter = 
COBParameterConverter.convert(executionContext.get(LoanCOBConstant.LOAN_COB_PARAMETER));
         List<Long> loanIds;
+        boolean isCatchUp = CatchUpFlagResolver.resolve(stepExecution);
         if (Objects.isNull(loanCOBParameter)
                 || (Objects.isNull(loanCOBParameter.getMinAccountId()) && 
Objects.isNull(loanCOBParameter.getMaxAccountId()))
                 || (loanCOBParameter.getMinAccountId().equals(0L) && 
loanCOBParameter.getMaxAccountId().equals(0L))) {
             loanIds = Collections.emptyList();
         } else {
             loanIds = 
retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter,
-                    
customJobParameterResolver.getCustomJobParameterById(stepExecution, 
LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME)
-                            .map(Boolean::parseBoolean).orElse(false));
-            if (loanIds.size() > 0) {
+                    isCatchUp);
+            if (!loanIds.isEmpty()) {
                 List<Long> lockedByCOBChunkProcessingAccountIds = 
getLoanIdsLockedWithChunkProcessingLock(loanIds);
                 loanIds.retainAll(lockedByCOBChunkProcessingAccountIds);
             }
@@ -73,8 +71,8 @@ public class LoanItemReader extends AbstractLoanItemReader {
     }
 
     private List<Long> getLoanIdsLockedWithChunkProcessingLock(List<Long> 
loanIds) {
-        List<LoanAccountLock> accountLocks = new ArrayList<>();
-        
accountLocks.addAll(loanLockingService.findAllByLoanIdInAndLockOwner(loanIds, 
LockOwner.LOAN_COB_CHUNK_PROCESSING));
+        List<LoanAccountLock> accountLocks = new ArrayList<>(
+                loanLockingService.findAllByLoanIdInAndLockOwner(loanIds, 
LockOwner.LOAN_COB_CHUNK_PROCESSING));
         return accountLocks.stream().map(LoanAccountLock::getLoanId).toList();
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java
index 3ac0a769f1..5a90c781f4 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java
@@ -36,23 +36,6 @@ import org.springframework.jdbc.core.JdbcTemplate;
 @Slf4j
 public class LoanLockingServiceImpl implements LoanLockingService {
 
-    private static final String NORMAL_LOAN_INSERT = """
-                INSERT INTO m_loan_account_locks (loan_id, version, 
lock_owner, lock_placed_on, lock_placed_on_cob_business_date)
-                SELECT loan.id, ?, ?, ?, ? FROM m_loan loan
-                    WHERE loan.id NOT IN (SELECT loan_id FROM 
m_loan_account_locks)
-                    AND loan.id BETWEEN ? AND ?
-                    AND loan.loan_status_id IN (100,200,300,303,304)
-                    AND (? = loan.last_closed_business_date OR 
loan.last_closed_business_date IS NULL)
-            """;
-    private static final String CATCH_UP_LOAN_INSERT = """
-                INSERT INTO m_loan_account_locks (loan_id, version, 
lock_owner, lock_placed_on, lock_placed_on_cob_business_date)
-                SELECT loan.id, ?, ?, ?, ? FROM m_loan loan
-                    WHERE loan.id NOT IN (SELECT loan_id FROM 
m_loan_account_locks)
-                    AND loan.id BETWEEN ? AND ?
-                    AND loan.loan_status_id IN (100,200,300,303,304)
-                    AND (? = loan.last_closed_business_date)
-            """;
-
     private static final String BATCH_LOAN_LOCK_INSERT = """
                 INSERT INTO m_loan_account_locks (loan_id, version, 
lock_owner, lock_placed_on, lock_placed_on_cob_business_date) VALUES (?,?,?,?,?)
             """;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/resolver/BusinessDateResolver.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/resolver/BusinessDateResolver.java
new file mode 100644
index 0000000000..e91dabbbc8
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/resolver/BusinessDateResolver.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.apache.fineract.cob.resolver;
+
+import java.time.LocalDate;
+import org.apache.fineract.cob.loan.LoanCOBConstant;
+import org.springframework.batch.core.StepExecution;
+
+public final class BusinessDateResolver {
+
+    private BusinessDateResolver() {}
+
+    public static LocalDate resolve(StepExecution stepExecution) {
+        Object bd = 
stepExecution.getJobExecution().getExecutionContext().get(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME);
+        return switch (bd) {
+            case null -> throw new IllegalStateException(
+                    "Missing BusinessDate in JobExecutionContext for 
jobExecutionId=" + stepExecution.getJobExecution().getId());
+            case String bdStr -> LocalDate.parse(bdStr);
+            case LocalDate bdLocalDate -> bdLocalDate;
+            default -> throw new IllegalStateException("BusinessDate value is 
unrecognizable: " + bd);
+        };
+    }
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/resolver/CatchUpFlagResolver.java
similarity index 52%
copy from 
fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
copy to 
fineract-provider/src/main/java/org/apache/fineract/cob/resolver/CatchUpFlagResolver.java
index 9916ffea78..25afa79c45 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/resolver/CatchUpFlagResolver.java
@@ -16,24 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.cob.loan;
+package org.apache.fineract.cob.resolver;
 
-import org.apache.fineract.cob.COBConstant;
+import org.apache.fineract.cob.loan.LoanCOBConstant;
+import org.springframework.batch.core.StepExecution;
 
-public final class LoanCOBConstant extends COBConstant {
+public final class CatchUpFlagResolver {
 
-    public static final String JOB_NAME = "LOAN_COB";
-    public static final String JOB_HUMAN_READABLE_NAME = "Loan COB";
-    public static final String LOAN_COB_JOB_NAME = "LOAN_CLOSE_OF_BUSINESS";
-    public static final String LOAN_COB_PARAMETER = "loanCobParameter";
-    public static final String LOAN_COB_WORKER_STEP = "loanCOBWorkerStep";
-
-    public static final String INLINE_LOAN_COB_JOB_NAME = "INLINE_LOAN_COB";
-    public static final String LOAN_IDS_PARAMETER_NAME = "LoanIds";
-
-    public static final String LOAN_COB_PARTITIONER_STEP = "Loan COB partition 
- Step";
-
-    private LoanCOBConstant() {
+    private CatchUpFlagResolver() {}
 
+    public static boolean resolve(StepExecution stepExecution) {
+        Object isCatchUp = 
stepExecution.getJobExecution().getExecutionContext().get(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME);
+        return switch (isCatchUp) {
+            case null -> false;
+            case String isCatchUpStr -> Boolean.parseBoolean(isCatchUpStr);
+            case Boolean b -> b;
+            default -> throw new IllegalStateException("isCatchUp value is 
unrecognizable: " + isCatchUp);
+        };
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/InputChannelInterceptor.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/InputChannelInterceptor.java
index 52ac7be931..271ef26fa1 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/InputChannelInterceptor.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/InputChannelInterceptor.java
@@ -45,8 +45,7 @@ public class InputChannelInterceptor implements 
ExecutorChannelInterceptor {
     @Override
     public void afterMessageHandled(@NonNull final Message<?> message, 
@NonNull final MessageChannel channel,
             @NonNull final MessageHandler handler, final Exception ex) {
-        log.debug("Cleaning up ThreadLocal context after message handling");
-        ThreadLocalContextUtil.reset();
+        afterHandleMessage();
     }
 
     public Message<StepExecutionRequest> beforeHandleMessage(Message<?> 
message) {
@@ -54,9 +53,14 @@ public class InputChannelInterceptor implements 
ExecutorChannelInterceptor {
     }
 
     public StepExecutionRequest beforeHandleMessage(ContextualMessage 
contextualMessage) {
-        log.debug("Initializing ThreadLocal context for message handling");
+        log.debug("Initializing ThreadLocal context for message handling: {}", 
contextualMessage);
         ThreadLocalContextUtil.init(contextualMessage.getContext());
         ThreadLocalContextUtil.setActionContext(ActionContext.COB);
         return contextualMessage.getStepExecutionRequest();
     }
+
+    public void afterHandleMessage() {
+        log.debug("Cleaning up ThreadLocal context after message handling");
+        ThreadLocalContextUtil.reset();
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/jms/JmsBatchWorkerMessageListener.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/jms/JmsBatchWorkerMessageListener.java
index f2d81e9e84..430a9aa7b8 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/jms/JmsBatchWorkerMessageListener.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/jms/JmsBatchWorkerMessageListener.java
@@ -58,6 +58,8 @@ public class JmsBatchWorkerMessageListener implements 
MessageListener, Initializ
             stepExecutionRequestHandler.handle(requestMessage.getPayload());
         } catch (Exception e) {
             log.error("Exception while processing JMS message", e);
+        } finally {
+            inputInterceptor.afterHandleMessage();
         }
 
         try {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/kafka/KafkaRemoteMessageListener.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/kafka/KafkaRemoteMessageListener.java
index efd668d97d..24a6513a00 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/kafka/KafkaRemoteMessageListener.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/kafka/KafkaRemoteMessageListener.java
@@ -50,6 +50,8 @@ public class KafkaRemoteMessageListener {
             stepExecutionRequestHandler.handle(stepExecutionRequest);
         } catch (Exception e) {
             log.error("Exception while processing Kafka message", e);
+        } finally {
+            inputInterceptor.afterHandleMessage();
         }
         acknowledgment.acknowledge();
         log.debug("Message was acknowledged {}", acknowledgment);
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java
 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java
index 3ff79b721f..a91f554c6a 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java
@@ -32,8 +32,6 @@ import java.time.LocalDate;
 import java.time.ZoneId;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Optional;
-import org.apache.fineract.cob.common.CustomJobParameterResolver;
 import org.apache.fineract.cob.data.COBParameter;
 import org.apache.fineract.cob.domain.LoanAccountLock;
 import org.apache.fineract.cob.domain.LockOwner;
@@ -44,6 +42,7 @@ import 
org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
+import org.springframework.batch.core.JobExecution;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.item.ExecutionContext;
@@ -62,9 +61,8 @@ public class ApplyLoanLockTaskletStepDefinitions implements 
En {
     private RetrieveLoanIdService retrieveLoanIdService = 
mock(RetrieveLoanIdService.class);
     private TransactionTemplate transactionTemplate = 
spy(TransactionTemplate.class);
 
-    private CustomJobParameterResolver customJobParameterResolver = 
mock(CustomJobParameterResolver.class);
     private ApplyLoanLockTasklet applyLoanLockTasklet = new 
ApplyLoanLockTasklet(fineractProperties, loanLockingService,
-            retrieveLoanIdService, customJobParameterResolver, 
transactionTemplate);
+            retrieveLoanIdService, transactionTemplate);
     private RepeatStatus resultItem;
     private StepContribution stepContribution;
 
@@ -74,7 +72,8 @@ public class ApplyLoanLockTaskletStepDefinitions implements 
En {
             HashMap<BusinessDateType, LocalDate> businessDateMap = new 
HashMap<>();
             businessDateMap.put(BusinessDateType.COB_DATE, 
LocalDate.now(ZoneId.systemDefault()));
             ThreadLocalContextUtil.setBusinessDates(businessDateMap);
-            StepExecution stepExecution = new StepExecution("test", null);
+            JobExecution jobExecution = new JobExecution(1L, null);
+            StepExecution stepExecution = new StepExecution("test", 
jobExecution);
             ExecutionContext executionContext = new ExecutionContext();
             COBParameter loanCOBParameter = new COBParameter(1L, 4L);
             executionContext.put(LoanCOBConstant.LOAN_COB_PARAMETER, 
loanCOBParameter);
@@ -117,7 +116,6 @@ public class ApplyLoanLockTaskletStepDefinitions implements 
En {
                 
lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks);
             }
             
transactionTemplate.setTransactionManager(mock(PlatformTransactionManager.class));
-            
lenient().when(customJobParameterResolver.getCustomJobParameterSet(any())).thenReturn(Optional.empty());
 
         });
 
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanCOBPartitionerTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanCOBPartitionerTest.java
index 799232c667..fdd90bb6cc 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanCOBPartitionerTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanCOBPartitionerTest.java
@@ -30,16 +30,14 @@ import org.apache.fineract.cob.COBBusinessStepService;
 import org.apache.fineract.cob.data.BusinessStepNameAndOrder;
 import org.apache.fineract.cob.data.COBParameter;
 import org.apache.fineract.cob.data.COBPartition;
-import org.apache.fineract.infrastructure.jobs.service.JobName;
 import org.apache.fineract.infrastructure.springbatch.PropertyService;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.explore.JobExplorer;
+import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.core.launch.JobExecutionNotRunningException;
 import org.springframework.batch.core.launch.JobOperator;
 import org.springframework.batch.core.launch.NoSuchJobExecutionException;
@@ -59,7 +57,11 @@ class LoanCOBPartitionerTest {
     @Mock
     private JobOperator jobOperator;
     @Mock
-    private JobExplorer jobExplorer;
+    private StepExecution stepExecution;
+    @Mock
+    private JobExecution jobExecution;
+    @Mock
+    private ExecutionContext executionContext;
 
     @Test
     public void testLoanCOBPartitioner() {
@@ -69,17 +71,19 @@ class LoanCOBPartitionerTest {
                 .thenReturn(BUSINESS_STEP_SET);
         when(retrieveLoanIdService.retrieveLoanCOBPartitions(1L, 
BUSINESS_DATE, false, 5))
                 .thenReturn(List.of(new COBPartition(1L,10L, 1L, 5L), new 
COBPartition(11L,20L, 2L, 4L)));
-        LoanCOBPartitioner loanCOBPartitioner = new 
LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator, jobExplorer, 1L);
-        loanCOBPartitioner.setBusinessDate(BUSINESS_DATE);
-        loanCOBPartitioner.setIsCatchUp(false);
+        when(stepExecution.getJobExecution()).thenReturn(jobExecution);
+        when(jobExecution.getExecutionContext()).thenReturn(executionContext);
+        
when(executionContext.get(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME)).thenReturn(BUSINESS_DATE);
+        
when(executionContext.get(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME)).thenReturn(false);
+        LoanCOBPartitioner loanCOBPartitioner = new 
LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator,stepExecution, 1L);
 
         //when
         Map<String, ExecutionContext> partitions = 
loanCOBPartitioner.partition(1);
 
         //then
         Assertions.assertEquals(2, partitions.size());
-        validatePartitions(partitions, 1, 1,  10);
-        validatePartitions(partitions, 2, 11,  20);
+        validatePartitions(partitions, 1, 1,  10, BUSINESS_DATE.toString(), 
"false");
+        validatePartitions(partitions, 2, 11,  20, BUSINESS_DATE.toString(), 
"false");
     }
 
     @Test
@@ -88,19 +92,16 @@ class LoanCOBPartitionerTest {
         
when(propertyService.getPartitionSize(LoanCOBConstant.JOB_NAME)).thenReturn(5);
         
when(cobBusinessStepService.getCOBBusinessSteps(LoanCOBBusinessStep.class, 
LoanCOBConstant.LOAN_COB_JOB_NAME))
                 .thenReturn(Set.of());
-        JobExecution jobExecution = Mockito.mock(JobExecution.class);
+
+        when(stepExecution.getJobExecution()).thenReturn(jobExecution);
         when(jobExecution.getId()).thenReturn(123L);
-        
when(jobExplorer.findRunningJobExecutions(JobName.LOAN_COB.name())).thenReturn(Set.of(jobExecution));
-        LoanCOBPartitioner loanCOBPartitioner = new 
LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator, jobExplorer, 1L);
-        loanCOBPartitioner.setBusinessDate(BUSINESS_DATE);
-        loanCOBPartitioner.setIsCatchUp(false);
+        LoanCOBPartitioner loanCOBPartitioner = new 
LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator, stepExecution, 1L);
 
         //when
         Map<String, ExecutionContext> partitions = 
loanCOBPartitioner.partition(1);
 
         //then
         Assertions.assertEquals(0, partitions.size());
-        verify(jobExplorer, 
times(1)).findRunningJobExecutions(JobName.LOAN_COB.name());
         verify(jobOperator, times(1)).stop(123L);
     }
 
@@ -112,24 +113,30 @@ class LoanCOBPartitionerTest {
                 .thenReturn(BUSINESS_STEP_SET);
         when(retrieveLoanIdService.retrieveLoanCOBPartitions(1L, 
BUSINESS_DATE, false, 5))
                 .thenReturn(List.of());
-        LoanCOBPartitioner loanCOBPartitioner = new 
LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator, jobExplorer, 1L);
-        loanCOBPartitioner.setBusinessDate(BUSINESS_DATE);
-        loanCOBPartitioner.setBusinessDate(BUSINESS_DATE);
-        loanCOBPartitioner.setIsCatchUp(false);
+        when(stepExecution.getJobExecution()).thenReturn(jobExecution);
+        when(jobExecution.getExecutionContext()).thenReturn(executionContext);
+        
when(executionContext.get(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME)).thenReturn(BUSINESS_DATE);
+        
when(executionContext.get(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME)).thenReturn(false);
+        LoanCOBPartitioner loanCOBPartitioner = new 
LoanCOBPartitioner(propertyService, cobBusinessStepService, 
retrieveLoanIdService, jobOperator,stepExecution, 1L);
 
         //when
         Map<String, ExecutionContext> partitions = 
loanCOBPartitioner.partition(1);
 
         //then
         Assertions.assertEquals(1, partitions.size());
-        validatePartitions(partitions, 1, 0,  0);
+        validatePartitions(partitions, 1, 0,  0, BUSINESS_DATE.toString(), 
"false");
     }
 
-    private void validatePartitions(Map<String, ExecutionContext> partitions, 
int index, long min, long max) {
+    private void validatePartitions(Map<String, ExecutionContext> partitions, 
int index, long min, long max, String businessDate,
+            String isCatchUp) {
         Assertions.assertEquals(BUSINESS_STEP_SET,
                 partitions.get(LoanCOBPartitioner.PARTITION_PREFIX + 
index).get(LoanCOBConstant.BUSINESS_STEPS));
         Assertions.assertEquals(new COBParameter(min, max),
                 partitions.get(LoanCOBPartitioner.PARTITION_PREFIX + 
index).get(LoanCOBConstant.LOAN_COB_PARAMETER));
         Assertions.assertEquals("partition_" + index, 
partitions.get(LoanCOBPartitioner.PARTITION_PREFIX + index).get("partition"));
+        Assertions.assertEquals(businessDate,
+                partitions.get(LoanCOBPartitioner.PARTITION_PREFIX + 
index).get(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME));
+        Assertions.assertEquals(isCatchUp,
+                partitions.get(LoanCOBPartitioner.PARTITION_PREFIX + 
index).get(LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME));
     }
 }
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java
 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java
index cc538e5cdc..ac4a858770 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java
@@ -59,8 +59,7 @@ public class LoanItemReaderStepDefinitions implements En {
 
     private LoanLockingService lockingService = mock(LoanLockingService.class);
 
-    private LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, customJobParameterResolver,
-            lockingService);
+    private LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, lockingService);
 
     private Loan loan = mock(Loan.class);
 
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderTest.java
index 81d822cb02..30dbc97078 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderTest.java
@@ -32,7 +32,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.IntStream;
-import org.apache.fineract.cob.common.CustomJobParameterResolver;
+import java.util.stream.Stream;
 import org.apache.fineract.cob.data.COBParameter;
 import org.apache.fineract.cob.domain.LoanAccountLock;
 import org.apache.fineract.cob.domain.LockOwner;
@@ -47,6 +47,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.batch.core.JobExecution;
 import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.item.ExecutionContext;
 
@@ -59,14 +60,13 @@ class LoanItemReaderTest {
     @Mock
     private RetrieveLoanIdService retrieveLoanIdService;
 
-    @Mock
-    private CustomJobParameterResolver customJobParameterResolver;
-
     @Mock
     private LoanLockingService loanLockingService;
 
     @Mock
     private StepExecution stepExecution;
+    @Mock
+    private JobExecution jobExecution;
 
     @Mock
     private ExecutionContext executionContext;
@@ -83,14 +83,15 @@ class LoanItemReaderTest {
     public void testLoanItemReaderSimple() throws Exception {
         // given
         ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, 
"test", "test", "UTC", null));
-        LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, customJobParameterResolver,
-                loanLockingService);
+        LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, loanLockingService);
         when(stepExecution.getExecutionContext()).thenReturn(executionContext);
+        when(stepExecution.getJobExecution()).thenReturn(jobExecution);
+        when(jobExecution.getExecutionContext()).thenReturn(executionContext);
         COBParameter loanCOBParameter = new COBParameter(1L, 5L);
         
when(executionContext.get(LoanCOBConstant.LOAN_COB_PARAMETER)).thenReturn(loanCOBParameter);
         
when(retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter,
 false))
                 .thenReturn(new ArrayList<>(List.of(1L, 2L, 3L, 4L, 5L)));
-        List<LoanAccountLock> accountLocks = List.of(1L, 2L, 3L, 4L, 
5L).stream()
+        List<LoanAccountLock> accountLocks = Stream.of(1L, 2L, 3L, 4L, 5L)
                 .map(l -> new LoanAccountLock(l, 
LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.of(2023, 7, 25))).toList();
         when(loanLockingService.findAllByLoanIdInAndLockOwner(List.of(1L, 2L, 
3L, 4L, 5L), LockOwner.LOAN_COB_CHUNK_PROCESSING))
                 .thenReturn(accountLocks);
@@ -111,9 +112,10 @@ class LoanItemReaderTest {
     public void testLoanItemReadNoOpenLoansFound() throws Exception {
         // given
         ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, 
"test", "test", "UTC", null));
-        LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, customJobParameterResolver,
-                loanLockingService);
+        LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, loanLockingService);
         when(stepExecution.getExecutionContext()).thenReturn(executionContext);
+        when(stepExecution.getJobExecution()).thenReturn(jobExecution);
+        when(jobExecution.getExecutionContext()).thenReturn(executionContext);
         COBParameter loanCOBParameter = new COBParameter(1L, 5L);
         
when(executionContext.get(LoanCOBConstant.LOAN_COB_PARAMETER)).thenReturn(loanCOBParameter);
         
when(retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter,
 false))
@@ -132,9 +134,10 @@ class LoanItemReaderTest {
     public void testLoanItemReaderMultiThreadRead() throws Exception {
         // given
         ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, 
"test", "test", "UTC", null));
-        LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, customJobParameterResolver,
-                loanLockingService);
+        LoanItemReader loanItemReader = new LoanItemReader(loanRepository, 
retrieveLoanIdService, loanLockingService);
         when(stepExecution.getExecutionContext()).thenReturn(executionContext);
+        when(stepExecution.getJobExecution()).thenReturn(jobExecution);
+        when(jobExecution.getExecutionContext()).thenReturn(executionContext);
         COBParameter loanCOBParameter = new COBParameter(1L, 100L);
         
when(executionContext.get(LoanCOBConstant.LOAN_COB_PARAMETER)).thenReturn(loanCOBParameter);
         
when(retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter,
 false))
@@ -160,7 +163,7 @@ class LoanItemReaderTest {
         }
         executorService.shutdown();
         boolean b = executorService.awaitTermination(5L, TimeUnit.SECONDS);
-        Assertions.assertEquals(true, b, "Executor did not terminate 
successfully");
+        Assertions.assertTrue(b, "Executor did not terminate successfully");
 
         // verify that this was called 100times, and for each loan it was 
called exactly once
         for (long i = 1; i <= 100; i++) {

Reply via email to