You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2023/04/17 15:50:53 UTC

[fineract] branch develop updated: FINERACT-1724: Use services instead of repositories in COB

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 748b77505 FINERACT-1724: Use services instead of repositories in COB
748b77505 is described below

commit 748b775051691fb48125650459d74cb0d59695e5
Author: Adam Saghy <ad...@gmail.com>
AuthorDate: Mon Apr 17 15:07:41 2023 +0200

    FINERACT-1724: Use services instead of repositories in COB
---
 .../cob/listener/AbstractLoanItemListener.java     | 12 ++--
 .../listener/ChunkProcessingLoanItemListener.java  |  6 +-
 .../cob/listener/InlineCOBLoanItemListener.java    |  6 +-
 .../fineract/cob/loan/AbstractLoanItemReader.java  |  2 -
 .../fineract/cob/loan/AbstractLoanItemWriter.java  |  5 +-
 .../fineract/cob/loan/ApplyLoanLockTasklet.java    | 22 ++-----
 .../fineract/cob/loan/InlineCOBLoanItemWriter.java |  5 +-
 .../cob/loan/LoanCOBManagerConfiguration.java      | 11 +---
 .../cob/loan/LoanCOBWorkerConfiguration.java       | 12 ++--
 .../fineract/cob/loan/LoanInlineCOBConfig.java     |  6 +-
 .../apache/fineract/cob/loan/LoanItemWriter.java   |  5 +-
 ...emWriter.java => LoanLockingConfiguration.java} | 26 ++++++---
 ...eLoanIdService.java => LoanLockingService.java} | 14 +++--
 ...oanTasklet.java => LoanLockingServiceImpl.java} | 68 ++++++++++++++--------
 .../apache/fineract/cob/loan/LockLoanTasklet.java  | 31 +---------
 .../RetrieveAllNonClosedLoanIdServiceImpl.java     |  6 ++
 .../fineract/cob/loan/RetrieveLoanIdService.java   |  4 ++
 .../cob/loan/StayedLockedLoansTasklet.java         |  5 +-
 .../listener/LoanItemListenerStepDefinitions.java  | 31 +++++-----
 .../loan/ApplyLoanLockTaskletStepDefinitions.java  | 25 ++++----
 .../cob/loan/FetchAndLockLoanStepDefinitions.java  | 34 +++++++----
 .../cob/loan/LoanItemWriterStepDefinitions.java    | 21 ++++---
 22 files changed, 173 insertions(+), 184 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/listener/AbstractLoanItemListener.java b/fineract-provider/src/main/java/org/apache/fineract/cob/listener/AbstractLoanItemListener.java
index e8246ccd8..b2606e889 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/listener/AbstractLoanItemListener.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/listener/AbstractLoanItemListener.java
@@ -21,13 +21,12 @@ package org.apache.fineract.cob.listener;
 import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW;
 
 import java.util.List;
-import java.util.Optional;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.cob.domain.LoanAccountLock;
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 import org.apache.fineract.cob.exceptions.LoanReadException;
+import org.apache.fineract.cob.loan.LoanLockingService;
 import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
 import org.apache.fineract.infrastructure.core.serialization.ThrowableSerialization;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -46,7 +45,7 @@ import org.springframework.transaction.support.TransactionTemplate;
 @RequiredArgsConstructor
 public abstract class AbstractLoanItemListener {
 
-    private final LoanAccountLockRepository accountLockRepository;
+    private final LoanLockingService loanLockingService;
 
     private final TransactionTemplate transactionTemplate;
 
@@ -57,9 +56,10 @@ public abstract class AbstractLoanItemListener {
             @Override
             protected void doInTransactionWithoutResult(@NotNull TransactionStatus status) {
                 for (Long loanId : loanIds) {
-                    Optional<LoanAccountLock> loanAccountLock = accountLockRepository.findByLoanIdAndLockOwner(loanId, getLockOwner());
-                    loanAccountLock.ifPresent(
-                            accountLock -> accountLock.setError(String.format(msg, loanId), ThrowableSerialization.serialize(e)));
+                    LoanAccountLock loanAccountLock = loanLockingService.findByLoanIdAndLockOwner(loanId, getLockOwner());
+                    if (loanAccountLock != null) {
+                        loanAccountLock.setError(String.format(msg, loanId), ThrowableSerialization.serialize(e));
+                    }
                 }
             }
         });
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/listener/ChunkProcessingLoanItemListener.java b/fineract-provider/src/main/java/org/apache/fineract/cob/listener/ChunkProcessingLoanItemListener.java
index 378083684..818dd8fd6 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/listener/ChunkProcessingLoanItemListener.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/listener/ChunkProcessingLoanItemListener.java
@@ -18,14 +18,14 @@
  */
 package org.apache.fineract.cob.listener;
 
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
+import org.apache.fineract.cob.loan.LoanLockingService;
 import org.springframework.transaction.support.TransactionTemplate;
 
 public class ChunkProcessingLoanItemListener extends AbstractLoanItemListener {
 
-    public ChunkProcessingLoanItemListener(LoanAccountLockRepository accountLockRepository, TransactionTemplate transactionTemplate) {
-        super(accountLockRepository, transactionTemplate);
+    public ChunkProcessingLoanItemListener(LoanLockingService loanLockingService, TransactionTemplate transactionTemplate) {
+        super(loanLockingService, transactionTemplate);
     }
 
     @Override
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/listener/InlineCOBLoanItemListener.java b/fineract-provider/src/main/java/org/apache/fineract/cob/listener/InlineCOBLoanItemListener.java
index cedeab776..548c21328 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/listener/InlineCOBLoanItemListener.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/listener/InlineCOBLoanItemListener.java
@@ -18,14 +18,14 @@
  */
 package org.apache.fineract.cob.listener;
 
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
+import org.apache.fineract.cob.loan.LoanLockingService;
 import org.springframework.transaction.support.TransactionTemplate;
 
 public class InlineCOBLoanItemListener extends AbstractLoanItemListener {
 
-    public InlineCOBLoanItemListener(LoanAccountLockRepository accountLockRepository, TransactionTemplate transactionTemplate) {
-        super(accountLockRepository, transactionTemplate);
+    public InlineCOBLoanItemListener(LoanLockingService loanLockingService, TransactionTemplate transactionTemplate) {
+        super(loanLockingService, transactionTemplate);
     }
 
     @Override
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java
index c92fdbf8d..40f39a6d3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java
@@ -39,8 +39,6 @@ public abstract class AbstractLoanItemReader implements ItemReader<Loan> {
 
     protected final LoanRepository loanRepository;
 
-    @Setter(AccessLevel.PROTECTED)
-    private List<Long> alreadyLockedOrProcessedAccounts;
     @Setter(AccessLevel.PROTECTED)
     private List<Long> remainingData;
     private Long loanId;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemWriter.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemWriter.java
index 4fa5e9d0f..061f90762 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemWriter.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemWriter.java
@@ -21,7 +21,6 @@ package org.apache.fineract.cob.loan;
 import java.util.List;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -32,14 +31,14 @@ import org.springframework.batch.item.data.RepositoryItemWriter;
 @RequiredArgsConstructor
 public abstract class AbstractLoanItemWriter extends RepositoryItemWriter<Loan> {
 
-    private final LoanAccountLockRepository accountLockRepository;
+    private final LoanLockingService loanLockingService;
 
     @Override
     public void write(@NotNull List<? extends Loan> items) throws Exception {
         if (!items.isEmpty()) {
             super.write(items);
             List<Long> loanIds = items.stream().map(AbstractPersistableCustom::getId).toList();
-            accountLockRepository.deleteByLoanIdInAndLockOwner(loanIds, getLockOwner());
+            loanLockingService.deleteByLoanIdInAndLockOwner(loanIds, getLockOwner());
         }
     }
 
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 4b550bd22..2f949a27c 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
@@ -30,25 +30,21 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.cob.data.LoanCOBParameter;
 import org.apache.fineract.cob.domain.LoanAccountLock;
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 import org.apache.fineract.infrastructure.core.config.FineractProperties;
-import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.scope.context.ChunkContext;
 import org.springframework.batch.core.step.tasklet.Tasklet;
 import org.springframework.batch.item.ExecutionContext;
 import org.springframework.batch.repeat.RepeatStatus;
-import org.springframework.jdbc.core.JdbcTemplate;
 
 @Slf4j
 @RequiredArgsConstructor
 public class ApplyLoanLockTasklet implements Tasklet {
 
-    private final LoanAccountLockRepository accountLockRepository;
     private final FineractProperties fineractProperties;
-    private final JdbcTemplate jdbcTemplate;
+    private final LoanLockingService loanLockingService;
     private final RetrieveLoanIdService retrieveLoanIdService;
 
     @Override
@@ -64,9 +60,9 @@ public class ApplyLoanLockTasklet implements Tasklet {
             loanIds = new ArrayList<>(
                     retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter));
         }
-        List<List<Long>> loanIdPartitions = Lists.partition(loanIds, fineractProperties.getQuery().getInClauseParameterSizeLimit());
+        List<List<Long>> loanIdPartitions = Lists.partition(loanIds, getInClauseParameterSizeLimit());
         List<LoanAccountLock> accountLocks = new ArrayList<>();
-        loanIdPartitions.forEach(loanIdPartition -> accountLocks.addAll(accountLockRepository.findAllByLoanIdIn(loanIdPartition)));
+        loanIdPartitions.forEach(loanIdPartition -> accountLocks.addAll(loanLockingService.findAllByLoanIdIn(loanIdPartition)));
 
         Map<Long, LoanAccountLock> alreadySoftLockedAccountsMap = accountLocks.stream()
                 .filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner()))
@@ -77,7 +73,7 @@ public class ApplyLoanLockTasklet implements Tasklet {
 
         List<Long> toBeProcessedLoanIds = new ArrayList<>(alreadySoftLockedAccountsMap.keySet());
 
-        upgradeToHardLock(toBeProcessedLoanIds);
+        loanLockingService.upgradeLock(toBeProcessedLoanIds, LockOwner.LOAN_COB_CHUNK_PROCESSING);
 
         toBeProcessedLoanIds.addAll(alreadyLockedByChunkProcessingAccountIds);
         List<Long> alreadyLockedByInlineCOBOrProcessedLoanIds = new ArrayList<>(loanIds);
@@ -88,16 +84,6 @@ public class ApplyLoanLockTasklet implements Tasklet {
         return RepeatStatus.FINISHED;
     }
 
-    private void upgradeToHardLock(List<Long> accountsToLock) {
-        jdbcTemplate.batchUpdate("""
-                    UPDATE m_loan_account_locks SET version= version + 1, lock_owner = ?, lock_placed_on = ? WHERE loan_id = ?
-                """, accountsToLock, getInClauseParameterSizeLimit(), (ps, id) -> {
-            ps.setString(1, LockOwner.LOAN_COB_CHUNK_PROCESSING.name());
-            ps.setObject(2, DateUtils.getOffsetDateTimeOfTenant());
-            ps.setLong(3, id);
-        });
-    }
-
     private int getInClauseParameterSizeLimit() {
         return fineractProperties.getQuery().getInClauseParameterSizeLimit();
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/InlineCOBLoanItemWriter.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/InlineCOBLoanItemWriter.java
index 9092cede0..9a839d326 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/InlineCOBLoanItemWriter.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/InlineCOBLoanItemWriter.java
@@ -18,13 +18,12 @@
  */
 package org.apache.fineract.cob.loan;
 
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 
 public class InlineCOBLoanItemWriter extends AbstractLoanItemWriter {
 
-    public InlineCOBLoanItemWriter(LoanAccountLockRepository accountLockRepository) {
-        super(accountLockRepository);
+    public InlineCOBLoanItemWriter(LoanLockingService loanLockingService) {
+        super(loanLockingService);
     }
 
     @Override
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 ac086dca8..07c9e962d 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
@@ -25,7 +25,6 @@ import org.apache.fineract.cob.listener.COBExecutionListenerRunner;
 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.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
 import org.springframework.batch.core.Job;
 import org.springframework.batch.core.Step;
 import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
@@ -44,7 +43,6 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.integration.channel.DirectChannel;
-import org.springframework.jdbc.core.JdbcTemplate;
 
 @Configuration
 @EnableBatchIntegration
@@ -76,10 +74,7 @@ public class LoanCOBManagerConfiguration {
     @Autowired
     private CustomJobParameterResolver customJobParameterResolver;
     @Autowired
-    private LoanRepository loanRepository;
-
-    @Autowired
-    private JdbcTemplate jdbcTemplate;
+    private LoanLockingService loanLockingService;
 
     @Bean
     @JobScope
@@ -123,7 +118,7 @@ public class LoanCOBManagerConfiguration {
     @Bean
     @JobScope
     public LockLoanTasklet lockLoanTasklet() {
-        return new LockLoanTasklet(jdbcTemplate);
+        return new LockLoanTasklet(loanLockingService);
     }
 
     @Bean
@@ -135,7 +130,7 @@ public class LoanCOBManagerConfiguration {
     @Bean
     @JobScope
     public StayedLockedLoansTasklet stayedLockedTasklet() {
-        return new StayedLockedLoansTasklet(businessEventNotifierService, loanRepository);
+        return new StayedLockedLoansTasklet(businessEventNotifierService, retrieveLoanIdService);
     }
 
     @Bean(name = "loanCOBJob")
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 ec6fff199..038353a0c 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
@@ -21,7 +21,6 @@ package org.apache.fineract.cob.loan;
 import org.apache.fineract.cob.COBBusinessStepService;
 import org.apache.fineract.cob.common.InitialisationTasklet;
 import org.apache.fineract.cob.common.ResetContextTasklet;
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.listener.ChunkProcessingLoanItemListener;
 import org.apache.fineract.infrastructure.core.config.FineractProperties;
 import org.apache.fineract.infrastructure.jobs.service.JobName;
@@ -41,7 +40,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.integration.channel.QueueChannel;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.transaction.support.TransactionTemplate;
 
 @Configuration
@@ -62,8 +60,6 @@ public class LoanCOBWorkerConfiguration {
     @Autowired
     private COBBusinessStepService cobBusinessStepService;
     @Autowired
-    private LoanAccountLockRepository accountLockRepository;
-    @Autowired
     private AppUserRepositoryWrapper userRepository;
     @Autowired
     private TransactionTemplate transactionTemplate;
@@ -73,7 +69,7 @@ public class LoanCOBWorkerConfiguration {
     @Autowired
     private FineractProperties fineractProperties;
     @Autowired
-    private JdbcTemplate jdbcTemplate;
+    private LoanLockingService loanLockingService;
 
     @Bean(name = LoanCOBConstant.LOAN_COB_WORKER_STEP)
     public Step loanCOBWorkerStep() {
@@ -120,12 +116,12 @@ public class LoanCOBWorkerConfiguration {
 
     @Bean
     public ChunkProcessingLoanItemListener loanItemListener() {
-        return new ChunkProcessingLoanItemListener(accountLockRepository, transactionTemplate);
+        return new ChunkProcessingLoanItemListener(loanLockingService, transactionTemplate);
     }
 
     @Bean
     public ApplyLoanLockTasklet applyLock() {
-        return new ApplyLoanLockTasklet(accountLockRepository, fineractProperties, jdbcTemplate, retrieveLoanIdService);
+        return new ApplyLoanLockTasklet(fineractProperties, loanLockingService, retrieveLoanIdService);
     }
 
     @Bean
@@ -148,7 +144,7 @@ public class LoanCOBWorkerConfiguration {
     @Bean
     @StepScope
     public LoanItemWriter cobWorkerItemWriter() {
-        LoanItemWriter repositoryItemWriter = new LoanItemWriter(accountLockRepository);
+        LoanItemWriter repositoryItemWriter = new LoanItemWriter(loanLockingService);
         repositoryItemWriter.setRepository(loanRepository);
         return repositoryItemWriter;
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java
index 78a9aa28d..9e92cd61a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java
@@ -59,6 +59,8 @@ public class LoanInlineCOBConfig {
     private TransactionTemplate transactionTemplate;
     @Autowired
     private CustomJobParameterRepository loanIdListRepository;
+    @Autowired
+    private LoanLockingService loanLockingService;
 
     @Bean
     public InlineLoanCOBBuildExecutionContextTasklet inlineLoanCOBBuildExecutionContextTasklet() {
@@ -103,14 +105,14 @@ public class LoanInlineCOBConfig {
 
     @Bean
     public InlineCOBLoanItemWriter inlineCobWorkerItemWriter() {
-        InlineCOBLoanItemWriter repositoryItemWriter = new InlineCOBLoanItemWriter(accountLockRepository);
+        InlineCOBLoanItemWriter repositoryItemWriter = new InlineCOBLoanItemWriter(loanLockingService);
         repositoryItemWriter.setRepository(loanRepository);
         return repositoryItemWriter;
     }
 
     @Bean
     public InlineCOBLoanItemListener inlineCobLoanItemListener() {
-        return new InlineCOBLoanItemListener(accountLockRepository, transactionTemplate);
+        return new InlineCOBLoanItemListener(loanLockingService, transactionTemplate);
     }
 
     @Bean
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemWriter.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemWriter.java
index 709e2bdd8..2696ee03a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemWriter.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemWriter.java
@@ -18,13 +18,12 @@
  */
 package org.apache.fineract.cob.loan;
 
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 
 public class LoanItemWriter extends AbstractLoanItemWriter {
 
-    public LoanItemWriter(LoanAccountLockRepository accountLockRepository) {
-        super(accountLockRepository);
+    public LoanItemWriter(LoanLockingService loanLockingService) {
+        super(loanLockingService);
     }
 
     @Override
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemWriter.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingConfiguration.java
similarity index 52%
copy from fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemWriter.java
copy to fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingConfiguration.java
index 709e2bdd8..660051907 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemWriter.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingConfiguration.java
@@ -19,16 +19,26 @@
 package org.apache.fineract.cob.loan;
 
 import org.apache.fineract.cob.domain.LoanAccountLockRepository;
-import org.apache.fineract.cob.domain.LockOwner;
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
 
-public class LoanItemWriter extends AbstractLoanItemWriter {
+@Configuration
+public class LoanLockingConfiguration {
 
-    public LoanItemWriter(LoanAccountLockRepository accountLockRepository) {
-        super(accountLockRepository);
-    }
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+    @Autowired
+    private FineractProperties fineractProperties;
+    @Autowired
+    private LoanAccountLockRepository loanAccountLockRepository;
 
-    @Override
-    protected LockOwner getLockOwner() {
-        return LockOwner.LOAN_COB_CHUNK_PROCESSING;
+    @Bean
+    @ConditionalOnMissingBean
+    public LoanLockingService retrieveLoanLockingService() {
+        return new LoanLockingServiceImpl(jdbcTemplate, fineractProperties, loanAccountLockRepository);
     }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveLoanIdService.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingService.java
similarity index 63%
copy from fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveLoanIdService.java
copy to fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingService.java
index eec70f899..3a7eadc69 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveLoanIdService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingService.java
@@ -21,16 +21,18 @@ package org.apache.fineract.cob.loan;
 import java.time.LocalDate;
 import java.util.List;
 import org.apache.fineract.cob.data.LoanCOBParameter;
-import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
+import org.apache.fineract.cob.domain.LoanAccountLock;
+import org.apache.fineract.cob.domain.LockOwner;
 
-public interface RetrieveLoanIdService {
+public interface LoanLockingService {
 
-    LoanCOBParameter retrieveMinAndMaxLoanIdsNDaysBehind(Long numberOfDays, LocalDate businessDate);
+    void applySoftLock(LocalDate lastClosedBusinessDate, LoanCOBParameter loanCOBParameter);
 
-    List<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsBehindDateOrNull(LocalDate businessDate, List<Long> loanIds);
+    void upgradeLock(List<Long> accountsToLock, LockOwner lockOwner);
 
-    List<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsOldestCobProcessed(LocalDate businessDate);
+    void deleteByLoanIdInAndLockOwner(List<Long> loanIds, LockOwner lockOwner);
 
-    List<Long> retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(LoanCOBParameter loanCOBParameter);
+    List<LoanAccountLock> findAllByLoanIdIn(List<Long> loanIds);
 
+    LoanAccountLock findByLoanIdAndLockOwner(Long loanId, LockOwner lockOwner);
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java
similarity index 56%
copy from fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java
copy to fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java
index b556b4a08..bf4c76a76 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java
@@ -19,45 +19,30 @@
 package org.apache.fineract.cob.loan;
 
 import java.time.LocalDate;
-import java.util.Objects;
+import java.util.List;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.cob.data.LoanCOBParameter;
+import org.apache.fineract.cob.domain.LoanAccountLock;
+import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
-import org.jetbrains.annotations.NotNull;
-import org.springframework.batch.core.StepContribution;
-import org.springframework.batch.core.scope.context.ChunkContext;
-import org.springframework.batch.core.step.tasklet.Tasklet;
-import org.springframework.batch.repeat.RepeatStatus;
 import org.springframework.jdbc.core.JdbcTemplate;
 
-@Slf4j
 @RequiredArgsConstructor
-public class LockLoanTasklet implements Tasklet {
+@Slf4j
+public class LoanLockingServiceImpl implements LoanLockingService {
 
     private final JdbcTemplate jdbcTemplate;
+    private final FineractProperties fineractProperties;
+    private final LoanAccountLockRepository loanAccountLockRepository;
 
     @Override
-    public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception {
-        String businessDateParameter = (String) contribution.getStepExecution().getJobExecution().getExecutionContext()
-                .get(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME);
-        LocalDate businessDate = LocalDate.parse(Objects.requireNonNull(businessDateParameter))
-                .minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND);
-        LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution().getExecutionContext()
-                .get(LoanCOBConstant.LOAN_COB_PARAMETER);
-        if (Objects.isNull(loanCOBParameter)
-                || (Objects.isNull(loanCOBParameter.getMinLoanId()) && Objects.isNull(loanCOBParameter.getMaxLoanId()))) {
-            loanCOBParameter = new LoanCOBParameter(0L, 0L);
-        }
-        applySoftLock(businessDate, loanCOBParameter);
+    public void applySoftLock(LocalDate lastClosedBusinessDate, LoanCOBParameter loanCOBParameter) {
 
-        return RepeatStatus.FINISHED;
-    }
-
-    private void applySoftLock(LocalDate businessDate, LoanCOBParameter loanCOBParameter) {
         LocalDate cobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE);
         jdbcTemplate.update("""
                     INSERT INTO m_loan_account_locks (loan_id, version, lock_owner, lock_placed_on, lock_placed_on_cob_business_date)
@@ -73,7 +58,40 @@ public class LockLoanTasklet implements Tasklet {
             ps.setObject(4, cobBusinessDate);
             ps.setObject(5, loanCOBParameter.getMinLoanId());
             ps.setObject(6, loanCOBParameter.getMaxLoanId());
-            ps.setObject(7, businessDate);
+            ps.setObject(7, lastClosedBusinessDate);
+        });
+    }
+
+    @Override
+    public void upgradeLock(List<Long> accountsToLock, LockOwner lockOwner) {
+        jdbcTemplate.batchUpdate("""
+                    UPDATE m_loan_account_locks SET version= version + 1, lock_owner = ?, lock_placed_on = ? WHERE loan_id = ?
+                """, accountsToLock, getInClauseParameterSizeLimit(), (ps, id) -> {
+            ps.setString(1, lockOwner.name());
+            ps.setObject(2, DateUtils.getOffsetDateTimeOfTenant());
+            ps.setLong(3, id);
+        });
+    }
+
+    @Override
+    public List<LoanAccountLock> findAllByLoanIdIn(List<Long> loanIds) {
+        return loanAccountLockRepository.findAllByLoanIdIn(loanIds);
+    }
+
+    @Override
+    public LoanAccountLock findByLoanIdAndLockOwner(Long loanId, LockOwner lockOwner) {
+        return loanAccountLockRepository.findByLoanIdAndLockOwner(loanId, lockOwner).orElseGet(() -> {
+            log.warn("There is no lock for loan account with id: {}", loanId);
+            return null;
         });
     }
+
+    @Override
+    public void deleteByLoanIdInAndLockOwner(List<Long> loanIds, LockOwner lockOwner) {
+        loanAccountLockRepository.deleteByLoanIdInAndLockOwner(loanIds, lockOwner);
+    }
+
+    private int getInClauseParameterSizeLimit() {
+        return fineractProperties.getQuery().getInClauseParameterSizeLimit();
+    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java
index b556b4a08..f313998aa 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java
@@ -23,28 +23,23 @@ import java.util.Objects;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.cob.data.LoanCOBParameter;
-import org.apache.fineract.cob.domain.LockOwner;
-import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
-import org.apache.fineract.infrastructure.core.service.DateUtils;
-import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.scope.context.ChunkContext;
 import org.springframework.batch.core.step.tasklet.Tasklet;
 import org.springframework.batch.repeat.RepeatStatus;
-import org.springframework.jdbc.core.JdbcTemplate;
 
 @Slf4j
 @RequiredArgsConstructor
 public class LockLoanTasklet implements Tasklet {
 
-    private final JdbcTemplate jdbcTemplate;
+    private final LoanLockingService loanLockingService;
 
     @Override
     public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception {
         String businessDateParameter = (String) contribution.getStepExecution().getJobExecution().getExecutionContext()
                 .get(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME);
-        LocalDate businessDate = LocalDate.parse(Objects.requireNonNull(businessDateParameter))
+        LocalDate lastClosedBusinessDate = LocalDate.parse(Objects.requireNonNull(businessDateParameter))
                 .minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND);
         LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution().getExecutionContext()
                 .get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -52,28 +47,8 @@ public class LockLoanTasklet implements Tasklet {
                 || (Objects.isNull(loanCOBParameter.getMinLoanId()) && Objects.isNull(loanCOBParameter.getMaxLoanId()))) {
             loanCOBParameter = new LoanCOBParameter(0L, 0L);
         }
-        applySoftLock(businessDate, loanCOBParameter);
+        loanLockingService.applySoftLock(lastClosedBusinessDate, loanCOBParameter);
 
         return RepeatStatus.FINISHED;
     }
-
-    private void applySoftLock(LocalDate businessDate, LoanCOBParameter loanCOBParameter) {
-        LocalDate cobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE);
-        jdbcTemplate.update("""
-                    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)
-                """, ps -> {
-            ps.setLong(1, 1);
-            ps.setString(2, LockOwner.LOAN_COB_PARTITIONING.name());
-            ps.setObject(3, DateUtils.getOffsetDateTimeOfTenant());
-            ps.setObject(4, cobBusinessDate);
-            ps.setObject(5, loanCOBParameter.getMinLoanId());
-            ps.setObject(6, loanCOBParameter.getMaxLoanId());
-            ps.setObject(7, businessDate);
-        });
-    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java
index 47aec31e3..258512ca3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java
@@ -22,6 +22,7 @@ import java.time.LocalDate;
 import java.util.List;
 import lombok.RequiredArgsConstructor;
 import org.apache.fineract.cob.data.LoanCOBParameter;
+import org.apache.fineract.cob.data.LoanIdAndExternalIdAndAccountNo;
 import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
@@ -54,4 +55,9 @@ public class RetrieveAllNonClosedLoanIdServiceImpl implements RetrieveLoanIdServ
                 ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE).minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND));
     }
 
+    @Override
+    public List<LoanIdAndExternalIdAndAccountNo> findAllStayedLockedByCobBusinessDate(LocalDate cobBusinessDate) {
+        return loanRepository.findAllStayedLockedByCobBusinessDate(cobBusinessDate);
+    }
+
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveLoanIdService.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveLoanIdService.java
index eec70f899..0063909cc 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveLoanIdService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveLoanIdService.java
@@ -21,7 +21,9 @@ package org.apache.fineract.cob.loan;
 import java.time.LocalDate;
 import java.util.List;
 import org.apache.fineract.cob.data.LoanCOBParameter;
+import org.apache.fineract.cob.data.LoanIdAndExternalIdAndAccountNo;
 import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
+import org.springframework.data.repository.query.Param;
 
 public interface RetrieveLoanIdService {
 
@@ -33,4 +35,6 @@ public interface RetrieveLoanIdService {
 
     List<Long> retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(LoanCOBParameter loanCOBParameter);
 
+    List<LoanIdAndExternalIdAndAccountNo> findAllStayedLockedByCobBusinessDate(@Param("cobBusinessDate") LocalDate cobBusinessDate);
+
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java
index 471098921..0b99ac397 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java
@@ -29,7 +29,6 @@ import org.apache.fineract.cob.data.LoanIdAndExternalIdAndAccountNo;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.scope.context.ChunkContext;
 import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -40,7 +39,7 @@ import org.springframework.batch.repeat.RepeatStatus;
 public class StayedLockedLoansTasklet implements Tasklet {
 
     private final BusinessEventNotifierService businessEventNotifierService;
-    private final LoanRepository loanRepository;
+    private final RetrieveLoanIdService retrieveLoanIdService;
 
     @Override
     public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
@@ -53,7 +52,7 @@ public class StayedLockedLoansTasklet implements Tasklet {
 
     private LoanAccountsStayedLockedData buildLoanAccountData() {
         LocalDate cobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE);
-        List<LoanIdAndExternalIdAndAccountNo> stayedLockedLoanAccounts = loanRepository
+        List<LoanIdAndExternalIdAndAccountNo> stayedLockedLoanAccounts = retrieveLoanIdService
                 .findAllStayedLockedByCobBusinessDate(cobBusinessDate);
         List<LoanAccountStayedLockedData> loanAccounts = new ArrayList<>();
         stayedLockedLoanAccounts.forEach(loanAccount -> {
diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/listener/LoanItemListenerStepDefinitions.java b/fineract-provider/src/test/java/org/apache/fineract/cob/listener/LoanItemListenerStepDefinitions.java
index 773b52180..2e7f1b659 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/cob/listener/LoanItemListenerStepDefinitions.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/cob/listener/LoanItemListenerStepDefinitions.java
@@ -30,11 +30,10 @@ import io.cucumber.java8.En;
 import java.time.LocalDate;
 import java.time.ZoneId;
 import java.util.List;
-import java.util.Optional;
 import org.apache.fineract.cob.domain.LoanAccountLock;
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 import org.apache.fineract.cob.exceptions.LoanReadException;
+import org.apache.fineract.cob.loan.LoanLockingService;
 import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -45,36 +44,34 @@ import org.springframework.transaction.support.TransactionTemplate;
 
 public class LoanItemListenerStepDefinitions implements En {
 
-    private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class);
+    private LoanLockingService loanLockingService = mock(LoanLockingService.class);
     private TransactionTemplate transactionTemplate = spy(TransactionTemplate.class);
 
-    private ChunkProcessingLoanItemListener loanItemListener = new ChunkProcessingLoanItemListener(accountLockRepository,
-            transactionTemplate);
+    private ChunkProcessingLoanItemListener loanItemListener = new ChunkProcessingLoanItemListener(loanLockingService, transactionTemplate);
 
     private Exception exception;
 
     private LoanAccountLock loanAccountLock;
-    private Loan loan = mock(Loan.class);
+    private final Loan loan = mock(Loan.class);
 
     public LoanItemListenerStepDefinitions() {
         Given("/^The LoanItemListener.onReadError method (.*)$/", (String action) -> {
             ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
             exception = new LoanReadException(1L, new RuntimeException("fail"));
             loanAccountLock = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
-            when(accountLockRepository.findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING))
-                    .thenReturn(Optional.of(loanAccountLock));
+            when(loanLockingService.findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING)).thenReturn(loanAccountLock);
             transactionTemplate.setTransactionManager(mock(PlatformTransactionManager.class));
             when(loan.getId()).thenReturn(1L);
         });
 
         When("LoanItemListener.onReadError method executed", () -> {
-            this.loanItemListener.onReadError(exception);
+            loanItemListener.onReadError(exception);
         });
 
         Then("LoanItemListener.onReadError result should match", () -> {
             verify(transactionTemplate, Mockito.times(1)).setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
             verify(transactionTemplate, Mockito.times(1)).execute(any());
-            verify(accountLockRepository, Mockito.times(1)).findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
+            verify(loanLockingService, Mockito.times(1)).findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
             assertEquals("Loan (id: 1) reading is failed", loanAccountLock.getError());
             assertNotNull(loanAccountLock.getStacktrace());
         });
@@ -83,20 +80,19 @@ public class LoanItemListenerStepDefinitions implements En {
             ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
             exception = new LoanReadException(1L, new RuntimeException("fail"));
             loanAccountLock = new LoanAccountLock(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
-            when(accountLockRepository.findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING))
-                    .thenReturn(Optional.of(loanAccountLock));
+            when(loanLockingService.findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING)).thenReturn(loanAccountLock);
             when(loan.getId()).thenReturn(2L);
             transactionTemplate.setTransactionManager(mock(PlatformTransactionManager.class));
         });
 
         When("LoanItemListener.onProcessError method executed", () -> {
-            this.loanItemListener.onProcessError(loan, exception);
+            loanItemListener.onProcessError(loan, exception);
         });
 
         Then("LoanItemListener.onProcessError result should match", () -> {
             verify(transactionTemplate, Mockito.times(1)).setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
             verify(transactionTemplate, Mockito.times(1)).execute(any());
-            verify(accountLockRepository, Mockito.times(1)).findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
+            verify(loanLockingService, Mockito.times(1)).findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
             assertEquals("Loan (id: 2) processing is failed", loanAccountLock.getError());
             assertNotNull(loanAccountLock.getStacktrace());
         });
@@ -105,20 +101,19 @@ public class LoanItemListenerStepDefinitions implements En {
             ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
             exception = new LoanReadException(3L, new RuntimeException("fail"));
             loanAccountLock = new LoanAccountLock(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
-            when(accountLockRepository.findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING))
-                    .thenReturn(Optional.of(loanAccountLock));
+            when(loanLockingService.findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING)).thenReturn(loanAccountLock);
             when(loan.getId()).thenReturn(3L);
             transactionTemplate.setTransactionManager(mock(PlatformTransactionManager.class));
         });
 
         When("LoanItemListener.onWriteError method executed", () -> {
-            this.loanItemListener.onWriteError(exception, List.of(loan));
+            loanItemListener.onWriteError(exception, List.of(loan));
         });
 
         Then("LoanItemListener.onWriteError result should match", () -> {
             verify(transactionTemplate, Mockito.times(1)).setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
             verify(transactionTemplate, Mockito.times(1)).execute(any());
-            verify(accountLockRepository, Mockito.times(1)).findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
+            verify(loanLockingService, Mockito.times(1)).findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
             assertEquals("Loan (id: 3) writing is failed", loanAccountLock.getError());
             assertNotNull(loanAccountLock.getStacktrace());
         });
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 1a3ba4c1e..37851a9da 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
@@ -31,7 +31,6 @@ import java.util.HashMap;
 import java.util.List;
 import org.apache.fineract.cob.data.LoanCOBParameter;
 import org.apache.fineract.cob.domain.LoanAccountLock;
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.config.FineractProperties;
@@ -43,18 +42,16 @@ import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.item.ExecutionContext;
 import org.springframework.batch.repeat.RepeatStatus;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
 
 public class ApplyLoanLockTaskletStepDefinitions implements En {
 
     ArgumentCaptor<List> valueCaptor = ArgumentCaptor.forClass(List.class);
-    private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class);
+    ArgumentCaptor<LockOwner> lockOwnerValueCaptor = ArgumentCaptor.forClass(LockOwner.class);
+    private LoanLockingService loanLockingService = mock(LoanLockingService.class);
     private FineractProperties fineractProperties = mock(FineractProperties.class);
-    private JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
     private FineractProperties.FineractQueryProperties fineractQueryProperties = mock(FineractProperties.FineractQueryProperties.class);
     private RetrieveLoanIdService retrieveLoanIdService = mock(RetrieveLoanIdService.class);
-    private ApplyLoanLockTasklet applyLoanLockTasklet = new ApplyLoanLockTasklet(accountLockRepository, fineractProperties, jdbcTemplate,
+    private ApplyLoanLockTasklet applyLoanLockTasklet = new ApplyLoanLockTasklet(fineractProperties, loanLockingService,
             retrieveLoanIdService);
     private RepeatStatus resultItem;
     private StepContribution stepContribution;
@@ -69,15 +66,15 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
             ExecutionContext executionContext = new ExecutionContext();
             LoanCOBParameter loanCOBParameter = new LoanCOBParameter(1L, 4L);
             executionContext.put(LoanCOBConstant.LOAN_COB_PARAMETER, loanCOBParameter);
-            lenient().when(this.retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter))
+            lenient().when(retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter))
                     .thenReturn(List.of(1L, 2L, 3L, 4L));
             stepExecution.setExecutionContext(executionContext);
-            this.stepContribution = new StepContribution(stepExecution);
+            stepContribution = new StepContribution(stepExecution);
 
             if ("error".equals(action)) {
                 lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
                 lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
-                lenient().when(this.accountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail"));
+                lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail"));
             } else {
                 LoanAccountLock lock1 = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
                 LoanAccountLock lock2 = new LoanAccountLock(2L, LockOwner.LOAN_COB_PARTITIONING, LocalDate.now(ZoneId.systemDefault()));
@@ -86,26 +83,26 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
                 List<LoanAccountLock> accountLocks = List.of(lock1, lock2, lock3);
                 lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
                 lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
-                lenient().when(this.accountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks);
+                lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks);
             }
 
         });
 
         When("ApplyLoanLockTasklet.execute method executed", () -> {
-            resultItem = this.applyLoanLockTasklet.execute(stepContribution, null);
+            resultItem = applyLoanLockTasklet.execute(stepContribution, null);
         });
 
         Then("ApplyLoanLockTasklet.execute result should match", () -> {
             assertEquals(RepeatStatus.FINISHED, resultItem);
-            verify(this.jdbcTemplate, Mockito.times(1)).batchUpdate(Mockito.anyString(), valueCaptor.capture(), Mockito.anyInt(),
-                    Mockito.any(ParameterizedPreparedStatementSetter.class));
+            verify(loanLockingService, Mockito.times(1)).upgradeLock(valueCaptor.capture(), lockOwnerValueCaptor.capture());
             List<Long> values = valueCaptor.getValue();
             assertEquals(2L, values.get(0));
+            assertEquals(LockOwner.LOAN_COB_CHUNK_PROCESSING, lockOwnerValueCaptor.getValue());
         });
 
         Then("throw exception ApplyLoanLockTasklet.execute method", () -> {
             assertThrows(RuntimeException.class, () -> {
-                resultItem = this.applyLoanLockTasklet.execute(stepContribution, null);
+                resultItem = applyLoanLockTasklet.execute(stepContribution, null);
             });
         });
     }
diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java
index 51ef56fa7..bbf77a9be 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java
@@ -19,8 +19,6 @@
 package org.apache.fineract.cob.loan;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -39,26 +37,26 @@ import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.config.FineractProperties;
 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.repeat.RepeatStatus;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.core.PreparedStatementSetter;
 
 public class FetchAndLockLoanStepDefinitions implements En {
 
     private final LoanAccountLockRepository loanAccountLockRepository = mock(LoanAccountLockRepository.class);
-
     private final FineractProperties fineractProperties = mock(FineractProperties.class);
     private final FineractProperties.FineractQueryProperties fineractQueryProperties = mock(
             FineractProperties.FineractQueryProperties.class);
     StepContribution contribution;
+    ArgumentCaptor<LocalDate> dateValueCaptor = ArgumentCaptor.forClass(LocalDate.class);
+    ArgumentCaptor<LoanCOBParameter> loanCOBParameterValueCaptor = ArgumentCaptor.forClass(LoanCOBParameter.class);
     private LockLoanTasklet lockLoanTasklet;
     private String action;
     private RepeatStatus result;
-    private JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
+    private final LoanLockingService loanLockingService = mock(LoanLockingService.class);
 
     public FetchAndLockLoanStepDefinitions() {
         Given("/^The FetchAndLockLoanTasklet.execute method with action (.*)$/", (String action) -> {
@@ -106,18 +104,21 @@ public class FetchAndLockLoanStepDefinitions implements En {
                         List.of(new LoanAccountLock(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()))));
             }
 
-            lockLoanTasklet = new LockLoanTasklet(jdbcTemplate);
+            lockLoanTasklet = new LockLoanTasklet(loanLockingService);
         });
 
         When("FetchAndLockLoanTasklet.execute method executed", () -> {
-            result = this.lockLoanTasklet.execute(contribution, null);
+            result = lockLoanTasklet.execute(contribution, null);
         });
 
         Then("FetchAndLockLoanTasklet.execute result should match", () -> {
             if ("empty steps".equals(action)) {
                 assertEquals(RepeatStatus.FINISHED, result);
             } else if ("good".equals(action)) {
-                verify(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
+                verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
+                assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
+                assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
+                assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
                 assertEquals(RepeatStatus.FINISHED, result);
                 LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
                         .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -125,7 +126,10 @@ public class FetchAndLockLoanStepDefinitions implements En {
                 assertEquals(1L, loanCOBParameter.getMinLoanId());
                 assertEquals(3L, loanCOBParameter.getMaxLoanId());
             } else if ("soft lock".equals(action)) {
-                verify(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
+                verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
+                assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
+                assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
+                assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
                 assertEquals(RepeatStatus.FINISHED, result);
                 LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
                         .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -133,7 +137,10 @@ public class FetchAndLockLoanStepDefinitions implements En {
                 assertEquals(1L, loanCOBParameter.getMinLoanId());
                 assertEquals(3L, loanCOBParameter.getMaxLoanId());
             } else if ("inline cob".equals(action)) {
-                verify(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
+                verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
+                assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
+                assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
+                assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
                 assertEquals(RepeatStatus.FINISHED, result);
                 LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
                         .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -141,7 +148,10 @@ public class FetchAndLockLoanStepDefinitions implements En {
                 assertEquals(1L, loanCOBParameter.getMinLoanId());
                 assertEquals(3L, loanCOBParameter.getMaxLoanId());
             } else if ("chunk processing".equals(action)) {
-                verify(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
+                verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
+                assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
+                assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
+                assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
                 assertEquals(RepeatStatus.FINISHED, result);
                 LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
                         .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemWriterStepDefinitions.java b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemWriterStepDefinitions.java
index 36ca22972..9df8182e4 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemWriterStepDefinitions.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemWriterStepDefinitions.java
@@ -25,17 +25,16 @@ import static org.mockito.Mockito.verify;
 import io.cucumber.java8.En;
 import java.util.Collections;
 import java.util.List;
-import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
 import org.mockito.Mockito;
 
 public class LoanItemWriterStepDefinitions implements En {
 
-    private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class);
-    private LoanRepository loanRepository = mock(LoanRepository.class);
+    private final LoanLockingService loanLockingService = mock(LoanLockingService.class);
+    private final LoanRepository loanRepository = mock(LoanRepository.class);
 
-    private LoanItemWriter loanItemWriter = new LoanItemWriter(accountLockRepository);
+    private final LoanItemWriter loanItemWriter = new LoanItemWriter(loanLockingService);
 
     private List<Loan> items;
 
@@ -45,24 +44,24 @@ public class LoanItemWriterStepDefinitions implements En {
             Loan loan = mock(Loan.class);
             lenient().when(loan.getId()).thenReturn(1L);
             if (action.equals("error")) {
-                this.items = Collections.emptyList();
+                items = Collections.emptyList();
             } else {
-                this.items = Collections.singletonList(loan);
-                lenient().doNothing().when(this.accountLockRepository).deleteByLoanIdInAndLockOwner(Mockito.anyList(), Mockito.any());
+                items = Collections.singletonList(loan);
+                lenient().doNothing().when(loanLockingService).deleteByLoanIdInAndLockOwner(Mockito.anyList(), Mockito.any());
             }
-            this.loanItemWriter.setRepository(loanRepository);
+            loanItemWriter.setRepository(loanRepository);
         });
 
         When("LoanItemWriter.write method executed", () -> {
-            this.loanItemWriter.write(items);
+            loanItemWriter.write(items);
         });
 
         Then("LoanItemWriter.write result should match", () -> {
-            verify(this.accountLockRepository, Mockito.times(1)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
+            verify(loanLockingService, Mockito.times(1)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
         });
 
         Then("LoanItemWriter.write should not call repository", () -> {
-            verify(this.accountLockRepository, Mockito.times(0)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
+            verify(loanLockingService, Mockito.times(0)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
         });
     }
 }