This is an automated email from the ASF dual-hosted git repository. avikg pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract-cn-deposit-account-management.git
The following commit(s) were added to refs/heads/develop by this push: new 9196049 [FINCN-346] Transaction execution error fix (#26) 9196049 is described below commit 9196049ab508de1f5320b89481b8f1942c258adf Author: Manoj <56669674+fynma...@users.noreply.github.com> AuthorDate: Mon Aug 9 17:31:34 2021 +0530 [FINCN-346] Transaction execution error fix (#26) * AL-52-account-transfer-txn * balance-api-collection-init * collections * transaction-execution-error-fix-by-retry --- .../fineract/cn/deposit/api/v1/EventConstants.java | 5 ++ .../cn/deposit/api/v1/PermittableGroupIds.java | 3 + .../deposit/listener/SubTxnTypeEventListener.java | 69 ++++++++++++++++++++++ .../deposit/listener/TransactionEventListener.java | 58 ++++++++++++++++++ .../command/handler/TransactionCommandHandler.java | 11 ++-- .../internal/service/TransactionService.java | 55 ++++++++++------- .../service/rest/CollectionsRestController.java | 8 +-- .../rest/ProductInstanceRestController.java | 30 +++++++++- .../service/rest/SubTxnTypeRestController.java | 8 +-- .../service/rest/TransactionRestController.java | 32 ++++++++-- service/src/main/resources/application.yml | 1 + 11 files changed, 236 insertions(+), 44 deletions(-) diff --git a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/EventConstants.java b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/EventConstants.java index 5bd1063..2c7060f 100644 --- a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/EventConstants.java +++ b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/EventConstants.java @@ -51,7 +51,12 @@ public interface EventConstants { String SELECTOR_PUT_PRODUCT_INSTANCE = SELECTOR_NAME + " = '" + PUT_PRODUCT_INSTANCE + "'"; String POST_SUB_TXN_TYPE = "post-sub-txn-type"; + String SELECTOR_POST_SUB_TXN_TYPE = SELECTOR_NAME + " = '" + POST_SUB_TXN_TYPE + "'"; String PUT_SUB_TXN_TYPE = "put-sub-txn-type"; + String SELECTOR_PUT_SUB_TXN_TYPE = SELECTOR_NAME + " = '" + PUT_SUB_TXN_TYPE + "'"; + + String POST_TXN = "post-txn"; + String SELECTOR_POST_TXN = SELECTOR_NAME + " = '" + POST_TXN + "'"; String ACTIVATE_PRODUCT_INSTANCE_COMMAND = "ACTIVATE"; String CLOSE_PRODUCT_INSTANCE_COMMAND = "CLOSE"; diff --git a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/PermittableGroupIds.java b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/PermittableGroupIds.java index 31c90c4..f558738 100644 --- a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/PermittableGroupIds.java +++ b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/PermittableGroupIds.java @@ -21,5 +21,8 @@ package org.apache.fineract.cn.deposit.api.v1; @SuppressWarnings("unused") public interface PermittableGroupIds { String DEFINITION_MANAGEMENT = "deposit__v1__definition"; + String DEF_SUB_TXN_MANAGEMENT = "deposit__v1__subtxn"; String INSTANCE_MANAGEMENT = "deposit__v1__instance"; + String TXN_MANAGEMENT = "deposit__v1__transaction"; + String COLLECTION_MANAGEMENT = "deposit__v1__collection"; } diff --git a/component-test/src/main/java/org/apache/fineract/cn/deposit/listener/SubTxnTypeEventListener.java b/component-test/src/main/java/org/apache/fineract/cn/deposit/listener/SubTxnTypeEventListener.java new file mode 100644 index 0000000..1fa5586 --- /dev/null +++ b/component-test/src/main/java/org/apache/fineract/cn/deposit/listener/SubTxnTypeEventListener.java @@ -0,0 +1,69 @@ +/* + * 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.cn.deposit.listener; + +import org.apache.fineract.cn.deposit.api.v1.EventConstants; +import org.apache.fineract.cn.deposit.service.ServiceConstants; +import org.apache.fineract.cn.lang.config.TenantHeaderFilter; +import org.apache.fineract.cn.test.listener.EventRecorder; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jms.annotation.JmsListener; +import org.springframework.messaging.handler.annotation.Header; + +/** + * @author manoj + */ +public class SubTxnTypeEventListener { + private final Logger logger; + private final EventRecorder eventRecorder; + + @Autowired + public SubTxnTypeEventListener(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, + final EventRecorder eventRecorder) { + super(); + this.logger = logger; + this.eventRecorder = eventRecorder; + } + + @JmsListener( + destination = EventConstants.DESTINATION, + selector = EventConstants.SELECTOR_POST_SUB_TXN_TYPE, + subscription = EventConstants.DESTINATION + ) + public void onCreateSubTxnType(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant, + final String payload) { + this.logger.debug("Product definition created."); + this.eventRecorder.event(tenant, EventConstants.POST_SUB_TXN_TYPE, payload, String.class); + } + + + @JmsListener( + destination = EventConstants.DESTINATION, + selector = EventConstants.SELECTOR_PUT_SUB_TXN_TYPE, + subscription = EventConstants.DESTINATION + ) + public void onUpdateSubTxnType(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant, + final String payload) { + this.logger.debug("Product definition created."); + this.eventRecorder.event(tenant, EventConstants.PUT_SUB_TXN_TYPE, payload, String.class); + } + + +} diff --git a/component-test/src/main/java/org/apache/fineract/cn/deposit/listener/TransactionEventListener.java b/component-test/src/main/java/org/apache/fineract/cn/deposit/listener/TransactionEventListener.java new file mode 100644 index 0000000..6738f76 --- /dev/null +++ b/component-test/src/main/java/org/apache/fineract/cn/deposit/listener/TransactionEventListener.java @@ -0,0 +1,58 @@ +/* + * 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.cn.deposit.listener; + +import org.apache.fineract.cn.command.annotation.EventEmitter; +import org.apache.fineract.cn.deposit.api.v1.EventConstants; +import org.apache.fineract.cn.deposit.service.ServiceConstants; +import org.apache.fineract.cn.lang.config.TenantHeaderFilter; +import org.apache.fineract.cn.test.listener.EventRecorder; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jms.annotation.JmsListener; +import org.springframework.messaging.handler.annotation.Header; + +/** + * @author manoj + */ +public class TransactionEventListener { + + private final Logger logger; + private final EventRecorder eventRecorder; + + @Autowired + public TransactionEventListener(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, + final EventRecorder eventRecorder) { + super(); + this.logger = logger; + this.eventRecorder = eventRecorder; + } + + @JmsListener( + destination = EventConstants.DESTINATION, + selector = EventConstants.SELECTOR_POST_TXN, + subscription = EventConstants.DESTINATION + ) + public void onPostTxn(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant, + final String payload) { + this.logger.debug("Product definition created."); + this.eventRecorder.event(tenant, EventConstants.POST_TXN, payload, String.class); + } + +} diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java index d9a4db0..4851a35 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java @@ -21,22 +21,19 @@ package org.apache.fineract.cn.deposit.service.internal.command.handler; import org.apache.fineract.cn.command.annotation.Aggregate; import org.apache.fineract.cn.command.annotation.CommandHandler; import org.apache.fineract.cn.command.annotation.CommandLogLevel; +import org.apache.fineract.cn.command.annotation.EventEmitter; +import org.apache.fineract.cn.deposit.api.v1.EventConstants; import org.apache.fineract.cn.deposit.api.v1.transaction.domain.data.TransactionResponseData; import org.apache.fineract.cn.deposit.service.ServiceConstants; import org.apache.fineract.cn.deposit.service.internal.command.TransactionCommand; -import org.apache.fineract.cn.deposit.service.internal.command.TransactionProcessedCommand; -import org.apache.fineract.cn.deposit.service.internal.repository.ProductInstanceEntity; import org.apache.fineract.cn.deposit.service.internal.service.TransactionService; -import org.apache.fineract.cn.lang.ServiceException; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotNull; -import java.time.Clock; -import java.time.LocalDateTime; -import java.util.Optional; @Aggregate public class TransactionCommandHandler { @@ -53,7 +50,9 @@ public class TransactionCommandHandler { @NotNull @Transactional @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO) + @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.POST_TXN) public TransactionResponseData performTransfer(@NotNull TransactionCommand command) { + switch (command.getAction()) { case WITHDRAWAL: { //command = dataValidator.validatePrepareTransfer(command); diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java index 97a3ac0..7c6753c 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java @@ -61,7 +61,6 @@ import java.util.stream.Collectors; public class TransactionService { private final Logger logger; private final LedgerManager ledgerManager; - private final ProductInstanceService productInstanceService; private final ProductDefinitionService productDefinitionService; private final ActionService actionService; private final SubTxnTypesService subTxnTypesService; @@ -73,12 +72,10 @@ public class TransactionService { @Autowired public TransactionService(@Qualifier(ServiceConstants.LOGGER_NAME) Logger logger, LedgerManager ledgerManager, - ProductInstanceService productInstanceService, ProductDefinitionService productDefinitionService, ActionService actionService, SubTxnTypesService subTxnTypesService, TransactionRepository transactionRepository, ProductInstanceRepository productInstanceRepository) { this.logger = logger; this.ledgerManager = ledgerManager; - this.productInstanceService = productInstanceService; this.productDefinitionService = productDefinitionService; this.actionService = actionService; this.subTxnTypesService = subTxnTypesService; @@ -92,7 +89,7 @@ public class TransactionService { AccountWrapper accountWrapper = validateAndGetAccount(request, request.getAccountId(), TransactionTypeEnum.WITHDRAWAL); LocalDateTime transactionDate = getNow(); //get txntype charges - List<Charge> charges = getCharges(accountWrapper.account.getIdentifier(), TransactionTypeEnum.WITHDRAWAL); + List<Charge> charges = getCharges(accountWrapper.productDefinition, TransactionTypeEnum.WITHDRAWAL); //todo: get subTxnType charges TransactionEntity txn = doWithdraw(request, accountWrapper, charges, getNow(), request.getAccountId()); @@ -109,7 +106,7 @@ public class TransactionService { AccountWrapper accountWrapper = validateAndGetAccount(request, request.getAccountId(), TransactionTypeEnum.DEPOSIT); LocalDateTime transactionDate = getNow(); //get txntype charges - List<Charge> charges = getCharges(accountWrapper.account.getIdentifier(), TransactionTypeEnum.DEPOSIT); + List<Charge> charges = getCharges(accountWrapper.productDefinition, TransactionTypeEnum.DEPOSIT); //todo: get subTxnType charges TransactionEntity txn = doDeposit(request, accountWrapper, charges, getNow(), request.getAccountId()); @@ -124,7 +121,7 @@ public class TransactionService { AccountWrapper toAccountWrapper = validateAndGetAccount(request, request.getToAccountId(), TransactionTypeEnum.DEPOSIT); LocalDateTime transactionDate = getNow(); //get txntype charges - List<Charge> charges = getCharges(fromAccountWrapper.account.getIdentifier(), TransactionTypeEnum.ACCOUNT_TRANSFER); + List<Charge> charges = getCharges(fromAccountWrapper.productDefinition, TransactionTypeEnum.ACCOUNT_TRANSFER); //todo: get subTxnType charges TransactionEntity txn = doWithdraw(request, fromAccountWrapper, charges, getNow(), request.getFromAccountId()); @@ -139,7 +136,9 @@ public class TransactionService { List<Charge> charges, LocalDateTime transactionDate, String accountId) { BigDecimal amount = request.getAmount().getAmount(); - TransactionEntity txn = createTransaction(request,TransactionTypeEnum.DEPOSIT, transactionDate, CREDIT, null, accountId); + TransactionEntity txn = createTransaction(request,TransactionTypeEnum.DEPOSIT, transactionDate, CREDIT, + null, accountId, accountWrapper.instance); + String debitAccountIdentifier = accountWrapper.productDefinition.getCashAccountIdentifier(); /* if subtxn is provided and it has an account configured the do debit that account*/ if(StringUtils.isNotBlank(request.getSubTxnId())){ @@ -149,6 +148,8 @@ public class TransactionService { if (subTxnTypeOpt.get().getLedgerAccount() != null) { debitAccountIdentifier = subTxnTypeOpt.get().getLedgerAccount(); } + }else{ + throw ServiceException.notFound("Sub Txn Type {0} not found.", request.getSubTxnId()); } } final JournalEntry journalEntry = createJournalEntry(txn.getIdentifier(), TransactionTypeEnum.DEPOSIT.getCode(), @@ -180,7 +181,8 @@ public class TransactionService { List<Charge> charges, LocalDateTime transactionDate, String accountId) { BigDecimal amount = request.getAmount().getAmount(); - TransactionEntity txn = createTransaction(request, TransactionTypeEnum.WITHDRAWAL, transactionDate, DEBIT, null, accountId); + TransactionEntity txn = createTransaction(request, TransactionTypeEnum.WITHDRAWAL, transactionDate, DEBIT, + null, accountId, accountWrapper.instance); String creditAccountIdentifier = accountWrapper.productDefinition.getCashAccountIdentifier(); /* if subtxn is provided and it has an account configured the do credit that account*/ @@ -191,6 +193,8 @@ public class TransactionService { if (subTxnTypeOpt.get().getLedgerAccount() != null) { creditAccountIdentifier = subTxnTypeOpt.get().getLedgerAccount(); } + }else{ + throw ServiceException.notFound("Sub Txn Type {0} not found.", request.getSubTxnId()); } } final JournalEntry journalEntry = createJournalEntry(txn.getIdentifier(), TransactionTypeEnum.WITHDRAWAL.getCode(), @@ -239,7 +243,8 @@ public class TransactionService { for(Charge charge : charges){ addCreditor(charge.getIncomeAccountIdentifier(), calcChargeAmount(amount, charge).doubleValue(), creditors); addDebtor(accountWrapper.account.getIdentifier(), calcChargeAmount(amount, charge).doubleValue(), debtors); - createTransaction(request,TransactionTypeEnum.CHARGES_PAYMENT, getNow(), DEBIT, txn, accountId); + createTransaction(request,TransactionTypeEnum.CHARGES_PAYMENT, getNow(), DEBIT, txn, + accountId, accountWrapper.instance); } } @@ -250,8 +255,10 @@ public class TransactionService { Account account = ledgerManager.findAccount(accountId); validateAccount(request.getAmount(), account); - ProductInstance product = productInstanceService.findByAccountIdentifier(accountId).get(); - ProductDefinition productDefinition = productDefinitionService.findProductDefinition(product.getProductIdentifier()).get(); + ProductInstanceEntity instance = productInstanceRepository.findByAccountIdentifier(accountId).orElseThrow( + () -> ServiceException.notFound("Account {0} not found", accountId) + ); + ProductDefinition productDefinition = productDefinitionService.findProductDefinition(instance.getProductDefinition().getIdentifier()).get(); Currency currency = productDefinition.getCurrency(); if (!currency.getCode().equals(request.getAmount().getCurrency())) @@ -263,7 +270,7 @@ public class TransactionService { if (txnType == TransactionTypeEnum.WITHDRAWAL && withdrawableBalance < request.getAmount().getAmount().doubleValue()) throw new UnsupportedOperationException(); - return new AccountWrapper(account, product, productDefinition, withdrawableBalance); + return new AccountWrapper(account, instance, productDefinition, withdrawableBalance); } Double getWithdrawableBalance(Account account, ProductDefinition productDefinition) { @@ -278,8 +285,10 @@ public class TransactionService { String accountId = account.getIdentifier(); if (account.getHolders() != null) { // customer account - ProductInstance product = productInstanceService.findByAccountIdentifier(accountId).get(); - ProductDefinition productDefinition = productDefinitionService.findProductDefinition(product.getProductIdentifier()).get(); + ProductInstanceEntity instance = productInstanceRepository.findByAccountIdentifier(accountId).orElseThrow( + () -> ServiceException.notFound("Account {0} not found", accountId) + ); + ProductDefinition productDefinition = productDefinitionService.findProductDefinition(instance.getProductDefinition().getIdentifier()).get(); if (!Boolean.TRUE.equals(productDefinition.getActive())) throw new UnsupportedOperationException("Product Definition is inactive"); @@ -296,7 +305,7 @@ public class TransactionService { throw new UnsupportedOperationException("Account is in state " + account.getState()); } - public List<Charge> getCharges(String accountIdentifier, TransactionTypeEnum transactionType) { + public List<Charge> getCharges(ProductDefinition productDefinition, TransactionTypeEnum transactionType) { List<Action> actions = actionService.fetchActions(); List<String> actionIds = actions @@ -305,9 +314,6 @@ public class TransactionService { .map(Action::getIdentifier) .collect(Collectors.toList()); - ProductInstance product = productInstanceService.findByAccountIdentifier(accountIdentifier).get(); - ProductDefinition productDefinition = productDefinitionService.findProductDefinition(product.getProductIdentifier()).get(); - return productDefinition.getCharges() .stream() .filter(charge -> actionIds.contains(charge.getActionIdentifier())) @@ -374,7 +380,8 @@ public class TransactionService { private TransactionEntity createTransaction(TransactionRequestData request, TransactionTypeEnum txnType, LocalDateTime transactionDate, String tranType, - TransactionEntity parent, String accountId) { + TransactionEntity parent, String accountId, + ProductInstanceEntity productInstanceEntity) { TransactionEntity txn = new TransactionEntity(); UUID uuid=UUID.randomUUID(); @@ -401,6 +408,8 @@ public class TransactionService { txn.setType(tranType); txn.setParentTransaction(parent); transactionRepository.save(txn); + productInstanceEntity.setLastTransactionDate(transactionDate); + this.productInstanceRepository.save(productInstanceEntity); return txn; } @@ -416,6 +425,7 @@ public class TransactionService { this.productInstanceRepository.save(productInstanceEntity); } + public List<StatementResponse> fetchStatement(String accountId, LocalDateTime fromDateTime, LocalDateTime toDateTime) { @@ -447,15 +457,16 @@ public class TransactionService { @NotNull private final Account account; @NotNull - private final ProductInstance product; + private final ProductInstanceEntity instance; @NotNull private final ProductDefinition productDefinition; @NotNull private final Double withdrawableBalance; - public AccountWrapper(Account account, ProductInstance product, ProductDefinition productDefinition, Double withdrawableBalance) { + public AccountWrapper(Account account, ProductInstanceEntity instance, + ProductDefinition productDefinition, Double withdrawableBalance) { this.account = account; - this.product = product; + this.instance = instance; this.productDefinition = productDefinition; this.withdrawableBalance = withdrawableBalance; } diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java index 3c0b30b..e33616b 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java @@ -50,7 +50,7 @@ public class CollectionsRestController { this.commandGateway = commandGateway; this.collectionsService = collectionsService; } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.INSTANCE_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.COLLECTION_MANAGEMENT) @RequestMapping( value = "", method = RequestMethod.POST, @@ -68,7 +68,7 @@ public class CollectionsRestController { } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.INSTANCE_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.COLLECTION_MANAGEMENT) @RequestMapping( value = "/{collectionsReference}", method = RequestMethod.PUT, @@ -85,7 +85,7 @@ public class CollectionsRestController { } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.INSTANCE_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.COLLECTION_MANAGEMENT) @RequestMapping( value = "/{collectionsReference}", method = RequestMethod.GET, @@ -99,6 +99,4 @@ public class CollectionsRestController { CollectionsResponse result = collectionsService.fetchCollection(collectionsReference); return ResponseEntity.ok(result); } - - } diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/ProductInstanceRestController.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/ProductInstanceRestController.java index f0cc9fb..135ebf5 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/ProductInstanceRestController.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/ProductInstanceRestController.java @@ -46,6 +46,7 @@ import org.apache.fineract.cn.lang.ServiceException; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -68,6 +69,10 @@ public class ProductInstanceRestController { private final ProductInstanceService productInstanceService; private final TransactionService transactionService; + + @Value("${config.txnMaxRetry}") + private Integer txnMaxRetry; + @Autowired public ProductInstanceRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, final CommandGateway commandGateway, @@ -88,9 +93,28 @@ public class ProductInstanceRestController { produces = MediaType.APPLICATION_JSON_VALUE ) @ResponseBody - public ResponseEntity<Void> create(@RequestBody @Valid final ProductInstance productInstance) { - this.commandGateway.process(new CreateProductInstanceCommand(productInstance)); - return ResponseEntity.accepted().build(); + public ResponseEntity<Void> create(@RequestBody @Valid final ProductInstance productInstance) throws Throwable{ + int retryCount = 0; + Exception e = null; + do { + retryCount++; + logger.info("Try transaction : " + retryCount + " of " + txnMaxRetry); + System.out.println("*******Try transaction : " + retryCount + " of " + txnMaxRetry); + try { + this.commandGateway.process(new CreateProductInstanceCommand(productInstance)); + return ResponseEntity.accepted().build(); + } catch (Exception ex) { + logger.info(ex.getClass().getCanonicalName()); + System.out.println(ex.getClass().getCanonicalName()); + logger.info(ex.getClass().getName()); + System.out.println(ex.getClass().getName()); + logger.info(ex.getMessage()); + System.out.println(ex.getMessage()); + e=ex; + } + } while (retryCount < txnMaxRetry); + //throw the last exception + throw e; } @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.INSTANCE_MANAGEMENT) diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/SubTxnTypeRestController.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/SubTxnTypeRestController.java index 8a875f4..53998e2 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/SubTxnTypeRestController.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/SubTxnTypeRestController.java @@ -57,7 +57,7 @@ public class SubTxnTypeRestController { this.service = service; } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEFINITION_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEF_SUB_TXN_MANAGEMENT) @RequestMapping( value = "", method = RequestMethod.POST, @@ -78,7 +78,7 @@ public class SubTxnTypeRestController { return ResponseEntity.accepted().build(); } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEFINITION_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEF_SUB_TXN_MANAGEMENT) @RequestMapping( value = "", method = RequestMethod.GET, @@ -92,7 +92,7 @@ public class SubTxnTypeRestController { } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEFINITION_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEF_SUB_TXN_MANAGEMENT) @RequestMapping( value = "/{identifier}", method = RequestMethod.GET, @@ -110,7 +110,7 @@ public class SubTxnTypeRestController { } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEFINITION_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.DEF_SUB_TXN_MANAGEMENT) @RequestMapping( value = "/{identifier}", method = RequestMethod.PUT, diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/TransactionRestController.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/TransactionRestController.java index 3b6e278..16ae9f0 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/TransactionRestController.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/TransactionRestController.java @@ -36,6 +36,7 @@ import org.apache.fineract.cn.lang.ServiceException; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -50,6 +51,10 @@ public class TransactionRestController { private final CommandGateway commandGateway; private final SubTxnTypesService service; + @Value("${config.txnMaxRetry}") + private Integer txnMaxRetry; + + @Autowired public TransactionRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, CommandGateway commandGateway, @@ -59,7 +64,7 @@ public class TransactionRestController { this.service = service; } - @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.INSTANCE_MANAGEMENT) + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TXN_MANAGEMENT) @RequestMapping( value = "", method = RequestMethod.POST, @@ -70,10 +75,29 @@ public class TransactionRestController { @ResponseBody ResponseEntity<TransactionResponseData> performTxn(@RequestParam("action") String action, @RequestBody TransactionRequestData requestData) throws Throwable { - CommandCallback<TransactionResponseData> result = commandGateway.process(new TransactionCommand(requestData, TransactionActionType.valueOf(action)), - TransactionResponseData.class); + int retryCount = 0; + Exception e = null; + do { + retryCount++; + logger.info("Try transaction : " + retryCount + " of " + txnMaxRetry); + System.out.println("*******Try transaction : " + retryCount + " of " + txnMaxRetry); + try { + CommandCallback<TransactionResponseData> result = commandGateway.process(new TransactionCommand(requestData, TransactionActionType.valueOf(action)), + TransactionResponseData.class); - return ResponseEntity.ok(result.get()); + return ResponseEntity.ok(result.get()); + } catch (Exception ex) { + logger.info(ex.getClass().getCanonicalName()); + System.out.println(ex.getClass().getCanonicalName()); + logger.info(ex.getClass().getName()); + System.out.println(ex.getClass().getName()); + logger.info(ex.getMessage()); + System.out.println(ex.getMessage()); + e=ex; + } + } while (retryCount < txnMaxRetry); + //throw the last exception + throw e; } } diff --git a/service/src/main/resources/application.yml b/service/src/main/resources/application.yml index 7a6ef48..94b23ec 100644 --- a/service/src/main/resources/application.yml +++ b/service/src/main/resources/application.yml @@ -78,5 +78,6 @@ config: fixedAccountId: true otpTokenLength: 6 tokenExpiryInSeconds: 172800 + txnMaxRetry : 5