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

myrle pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-customer.git

commit 5e05d4a57244184ef3b92757dc79b975cc489dad
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Fri Oct 20 12:45:17 2017 +0200

    TestCustomer.shouldDeletePortrait was failing intermittently with an
    InternalServerError resulting from a NullPointerException in the GET
    endpoint implementation.  The delete transaction was getting committed
    between the query if the portrait exits and the actually acquisition of
    the portrait in the rest implementation.  I changed the repository to
    return an Optional.empty instead of a null if the identifier doesn't
    correspond to a customer.  This enabled me to replace two calls with one
    and eliminate the potential for a race condition.  This in turn probably
    eliminated several other potential NullPointerExceptions.
---
 .../main/java/io/mifos/customer/TestCustomer.java  |   6 +-
 .../command/handler/CustomerAggregate.java         |  87 +++------
 .../command/handler/DocumentCommandHandler.java    |  18 +-
 .../internal/command/handler/TaskAggregate.java    |  12 +-
 .../internal/repository/CommandRepository.java     |   4 +-
 .../internal/repository/CustomerRepository.java    |   4 +-
 .../repository/IdentificationCardRepository.java   |   4 +-
 .../service/internal/service/CustomerService.java  | 213 ++++++++-------------
 .../service/internal/service/TaskService.java      |   7 +-
 .../rest/controller/CustomerRestController.java    |  21 +-
 10 files changed, 148 insertions(+), 228 deletions(-)

diff --git a/component-test/src/main/java/io/mifos/customer/TestCustomer.java 
b/component-test/src/main/java/io/mifos/customer/TestCustomer.java
index d11d5a8..5ce3f66 100644
--- a/component-test/src/main/java/io/mifos/customer/TestCustomer.java
+++ b/component-test/src/main/java/io/mifos/customer/TestCustomer.java
@@ -411,17 +411,17 @@ public class TestCustomer extends AbstractCustomerTest {
 
     this.customerManager.createCustomer(customer);
 
-    this.eventRecorder.wait(CustomerEventConstants.POST_CUSTOMER, 
customer.getIdentifier());
+    
Assert.assertTrue(this.eventRecorder.wait(CustomerEventConstants.POST_CUSTOMER, 
customer.getIdentifier()));
 
     final MockMultipartFile firstFile = new MockMultipartFile("portrait", 
"test.png", MediaType.IMAGE_PNG_VALUE, "i don't care".getBytes());
 
     this.customerManager.postPortrait(customer.getIdentifier(), firstFile);
 
-    this.eventRecorder.wait(CustomerEventConstants.POST_PORTRAIT, 
customer.getIdentifier());
+    
Assert.assertTrue(this.eventRecorder.wait(CustomerEventConstants.POST_PORTRAIT, 
customer.getIdentifier()));
 
     this.customerManager.deletePortrait(customer.getIdentifier());
 
-    this.eventRecorder.wait(CustomerEventConstants.DELETE_PORTRAIT, 
customer.getIdentifier());
+    
Assert.assertTrue(this.eventRecorder.wait(CustomerEventConstants.DELETE_PORTRAIT,
 customer.getIdentifier()));
 
     this.customerManager.getPortrait(customer.getIdentifier());
   }
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/command/handler/CustomerAggregate.java
 
b/service/src/main/java/io/mifos/customer/service/internal/command/handler/CustomerAggregate.java
index fa306a5..07e5ebc 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/command/handler/CustomerAggregate.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/command/handler/CustomerAggregate.java
@@ -25,53 +25,11 @@ import io.mifos.customer.api.v1.CustomerEventConstants;
 import io.mifos.customer.api.v1.domain.Command;
 import io.mifos.customer.api.v1.domain.Customer;
 import io.mifos.customer.api.v1.events.ScanEvent;
-import io.mifos.customer.catalog.service.internal.repository.CatalogEntity;
-import io.mifos.customer.catalog.service.internal.repository.CatalogRepository;
-import io.mifos.customer.catalog.service.internal.repository.FieldEntity;
-import io.mifos.customer.catalog.service.internal.repository.FieldRepository;
-import io.mifos.customer.catalog.service.internal.repository.FieldValueEntity;
-import 
io.mifos.customer.catalog.service.internal.repository.FieldValueRepository;
-import io.mifos.customer.service.ServiceConstants;
-import io.mifos.customer.service.internal.command.ActivateCustomerCommand;
-import io.mifos.customer.service.internal.command.CloseCustomerCommand;
-import io.mifos.customer.service.internal.command.CreateCustomerCommand;
-import 
io.mifos.customer.service.internal.command.CreateIdentificationCardCommand;
-import 
io.mifos.customer.service.internal.command.CreateIdentificationCardScanCommand;
-import io.mifos.customer.service.internal.command.CreatePortraitCommand;
-import 
io.mifos.customer.service.internal.command.DeleteIdentificationCardCommand;
-import 
io.mifos.customer.service.internal.command.DeleteIdentificationCardScanCommand;
-import io.mifos.customer.service.internal.command.DeletePortraitCommand;
-import io.mifos.customer.service.internal.command.LockCustomerCommand;
-import io.mifos.customer.service.internal.command.ReopenCustomerCommand;
-import io.mifos.customer.service.internal.command.UnlockCustomerCommand;
-import io.mifos.customer.service.internal.command.UpdateAddressCommand;
-import io.mifos.customer.service.internal.command.UpdateContactDetailsCommand;
-import io.mifos.customer.service.internal.command.UpdateCustomerCommand;
-import 
io.mifos.customer.service.internal.command.UpdateIdentificationCardCommand;
-import io.mifos.customer.service.internal.mapper.AddressMapper;
-import io.mifos.customer.service.internal.mapper.CommandMapper;
-import io.mifos.customer.service.internal.mapper.ContactDetailMapper;
-import io.mifos.customer.service.internal.mapper.CustomerMapper;
-import io.mifos.customer.service.internal.mapper.FieldValueMapper;
-import io.mifos.customer.service.internal.mapper.IdentificationCardMapper;
-import io.mifos.customer.service.internal.mapper.IdentificationCardScanMapper;
-import io.mifos.customer.service.internal.mapper.PortraitMapper;
-import io.mifos.customer.service.internal.repository.AddressEntity;
-import io.mifos.customer.service.internal.repository.AddressRepository;
-import io.mifos.customer.service.internal.repository.CommandRepository;
-import io.mifos.customer.service.internal.repository.ContactDetailEntity;
-import io.mifos.customer.service.internal.repository.ContactDetailRepository;
-import io.mifos.customer.service.internal.repository.CustomerEntity;
-import io.mifos.customer.service.internal.repository.CustomerRepository;
-import io.mifos.customer.service.internal.repository.IdentificationCardEntity;
-import 
io.mifos.customer.service.internal.repository.IdentificationCardRepository;
-import 
io.mifos.customer.service.internal.repository.IdentificationCardScanEntity;
-import 
io.mifos.customer.service.internal.repository.IdentificationCardScanRepository;
-import io.mifos.customer.service.internal.repository.PortraitEntity;
-import io.mifos.customer.service.internal.repository.PortraitRepository;
-import org.slf4j.Logger;
+import io.mifos.customer.catalog.service.internal.repository.*;
+import io.mifos.customer.service.internal.command.*;
+import io.mifos.customer.service.internal.mapper.*;
+import io.mifos.customer.service.internal.repository.*;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -84,11 +42,9 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-@SuppressWarnings("unused")
+@SuppressWarnings({"unused", "UnusedReturnValue"})
 @Aggregate
 public class CustomerAggregate {
-
-  private final Logger logger;
   private final AddressRepository addressRepository;
   private final CustomerRepository customerRepository;
   private final IdentificationCardRepository identificationCardRepository;
@@ -102,8 +58,7 @@ public class CustomerAggregate {
   private final TaskAggregate taskAggregate;
 
   @Autowired
-  public CustomerAggregate(@Qualifier(ServiceConstants.LOGGER_NAME) final 
Logger logger,
-                           final AddressRepository addressRepository,
+  public CustomerAggregate(final AddressRepository addressRepository,
                            final CustomerRepository customerRepository,
                            final IdentificationCardRepository 
identificationCardRepository,
                            final IdentificationCardScanRepository 
identificationCardScanRepository,
@@ -115,7 +70,6 @@ public class CustomerAggregate {
                            final CommandRepository commandRepository,
                            final TaskAggregate taskAggregate) {
     super();
-    this.logger = logger;
     this.addressRepository = addressRepository;
     this.customerRepository = customerRepository;
     this.identificationCardRepository = identificationCardRepository;
@@ -170,7 +124,7 @@ public class CustomerAggregate {
   public String updateCustomer(final UpdateCustomerCommand 
updateCustomerCommand) {
     final Customer customer = updateCustomerCommand.customer();
 
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(customer.getIdentifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(customer.getIdentifier());
 
     customerEntity.setGivenName(customer.getGivenName());
     customerEntity.setMiddleName(customer.getMiddleName());
@@ -218,7 +172,7 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.ACTIVATE_CUSTOMER)
   public String activateCustomer(final ActivateCustomerCommand 
activateCustomerCommand) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(activateCustomerCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(activateCustomerCommand.identifier());
 
     if (this.taskAggregate.openTasksForCustomerExist(customerEntity, 
Command.Action.ACTIVATE.name())) {
       throw ServiceException.conflict("Open Tasks for customer {0} exists.", 
activateCustomerCommand.identifier());
@@ -241,7 +195,8 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.LOCK_CUSTOMER)
   public String lockCustomer(final LockCustomerCommand lockCustomerCommand) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(lockCustomerCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(lockCustomerCommand.identifier());
+
     customerEntity.setCurrentState(Customer.State.LOCKED.name());
     customerEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
     customerEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
@@ -261,7 +216,7 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.UNLOCK_CUSTOMER)
   public String unlockCustomer(final UnlockCustomerCommand 
unlockCustomerCommand) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(unlockCustomerCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(unlockCustomerCommand.identifier());
 
     if (this.taskAggregate.openTasksForCustomerExist(customerEntity, 
Command.Action.UNLOCK.name())) {
       throw ServiceException.conflict("Open Tasks for customer {0} exists.", 
unlockCustomerCommand.identifier());
@@ -284,7 +239,8 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.CLOSE_CUSTOMER)
   public String closeCustomer(final CloseCustomerCommand closeCustomerCommand) 
{
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(closeCustomerCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(closeCustomerCommand.identifier());
+
     customerEntity.setCurrentState(Customer.State.CLOSED.name());
     customerEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
     customerEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
@@ -304,7 +260,7 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.REOPEN_CUSTOMER)
   public String reopenCustomer(final ReopenCustomerCommand 
reopenCustomerCommand) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(reopenCustomerCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(reopenCustomerCommand.identifier());
 
     if (this.taskAggregate.openTasksForCustomerExist(customerEntity, 
Command.Action.REOPEN.name())) {
       throw ServiceException.conflict("Open Tasks for customer {0} exists.", 
reopenCustomerCommand.identifier());
@@ -327,7 +283,7 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.PUT_ADDRESS)
   public String updateAddress(final UpdateAddressCommand updateAddressCommand) 
{
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(updateAddressCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(updateAddressCommand.identifier());
     customerEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
     customerEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
 
@@ -347,7 +303,7 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.PUT_CONTACT_DETAILS)
   public String updateContactDetails(final UpdateContactDetailsCommand 
updateContactDetailsCommand) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(updateContactDetailsCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(updateContactDetailsCommand.identifier());
     customerEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
     customerEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
 
@@ -374,7 +330,7 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.POST_IDENTIFICATION_CARD)
   public String createIdentificationCard(final CreateIdentificationCardCommand 
createIdentificationCardCommand) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(createIdentificationCardCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(createIdentificationCardCommand.identifier());
 
     final IdentificationCardEntity identificationCardEntity = 
IdentificationCardMapper.map(createIdentificationCardCommand.identificationCard());
 
@@ -507,7 +463,7 @@ public class CustomerAggregate {
       return null;
     }
 
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(createPortraitCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(createPortraitCommand.identifier());
 
     final PortraitEntity portraitEntity = 
PortraitMapper.map(createPortraitCommand.portrait());
     portraitEntity.setCustomer(customerEntity);
@@ -525,7 +481,7 @@ public class CustomerAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.DELETE_PORTRAIT)
   public String deletePortrait(final DeletePortraitCommand 
deletePortraitCommand) throws IOException {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(deletePortraitCommand.identifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(deletePortraitCommand.identifier());
 
     this.portraitRepository.deleteByCustomer(customerEntity);
 
@@ -557,4 +513,9 @@ public class CustomerAggregate {
             .collect(Collectors.toList())
     );
   }
+
+  private CustomerEntity findCustomerEntityOrThrow(String identifier) {
+    return this.customerRepository.findByIdentifier(identifier)
+        .orElseThrow(() -> ServiceException.notFound("Customer ''{0}'' not 
found", identifier));
+  }
 }
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/command/handler/DocumentCommandHandler.java
 
b/service/src/main/java/io/mifos/customer/service/internal/command/handler/DocumentCommandHandler.java
index 9c27aab..c91fcc0 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/command/handler/DocumentCommandHandler.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/command/handler/DocumentCommandHandler.java
@@ -71,11 +71,9 @@ public class DocumentCommandHandler {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.POST_DOCUMENT)
   public DocumentEvent process(final CreateDocumentCommand command) throws 
IOException {
-
-
-    final CustomerEntity customerEntity = 
customerRepository.findByIdentifier(command.getCustomerIdentifier());
-    final DocumentEntity documentEntity = 
DocumentMapper.map(command.getCustomerDocument(), customerEntity);
-    documentRepository.save(documentEntity);
+    customerRepository.findByIdentifier(command.getCustomerIdentifier())
+        .map(customerEntity -> 
DocumentMapper.map(command.getCustomerDocument(), customerEntity))
+        .ifPresent(documentRepository::save);
 
     return new DocumentEvent(command.getCustomerIdentifier(), 
command.getCustomerDocument().getIdentifier());
   }
@@ -90,10 +88,12 @@ public class DocumentCommandHandler {
             ServiceException.notFound("Document ''{0}'' for customer ''{1}'' 
not found",
                 command.getCustomerDocument().getIdentifier(), 
command.getCustomerIdentifier()));
 
-    final CustomerEntity customerEntity = 
customerRepository.findByIdentifier(command.getCustomerIdentifier());
-    final DocumentEntity documentEntity = 
DocumentMapper.map(command.getCustomerDocument(), customerEntity);
-    documentEntity.setId(existingDocument.getId());
-    documentRepository.save(documentEntity);
+    customerRepository.findByIdentifier(command.getCustomerIdentifier())
+        .map(customerEntity -> 
DocumentMapper.map(command.getCustomerDocument(), customerEntity))
+        .ifPresent(documentEntity -> {
+          documentEntity.setId(existingDocument.getId());
+          documentRepository.save(documentEntity);
+        });
 
     return new DocumentEvent(command.getCustomerIdentifier(), 
command.getCustomerDocument().getIdentifier());
   }
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/command/handler/TaskAggregate.java
 
b/service/src/main/java/io/mifos/customer/service/internal/command/handler/TaskAggregate.java
index 5e1bac6..ab4cb41 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/command/handler/TaskAggregate.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/command/handler/TaskAggregate.java
@@ -19,6 +19,7 @@ import io.mifos.core.api.util.UserContextHolder;
 import io.mifos.core.command.annotation.Aggregate;
 import io.mifos.core.command.annotation.CommandHandler;
 import io.mifos.core.command.annotation.EventEmitter;
+import io.mifos.core.lang.ServiceException;
 import io.mifos.customer.api.v1.CustomerEventConstants;
 import io.mifos.customer.api.v1.domain.Command;
 import io.mifos.customer.api.v1.domain.TaskDefinition;
@@ -95,8 +96,7 @@ public class TaskAggregate {
     final TaskDefinitionEntity taskDefinitionEntity =
         
this.taskDefinitionRepository.findByIdentifier(addTaskDefinitionToCustomerCommand.taskIdentifier());
 
-    final CustomerEntity customerEntity =
-        
this.customerRepository.findByIdentifier(addTaskDefinitionToCustomerCommand.customerIdentifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(addTaskDefinitionToCustomerCommand.customerIdentifier());
 
     
this.taskInstanceRepository.save(TaskInstanceMapper.create(taskDefinitionEntity,
 customerEntity));
 
@@ -107,8 +107,7 @@ public class TaskAggregate {
   @CommandHandler
   @EventEmitter(selectorName = CustomerEventConstants.SELECTOR_NAME, 
selectorValue = CustomerEventConstants.PUT_CUSTOMER)
   public String executeTaskForCustomer(final ExecuteTaskForCustomerCommand 
executeTaskForCustomerCommand) {
-    final CustomerEntity customerEntity =
-        
this.customerRepository.findByIdentifier(executeTaskForCustomerCommand.customerIdentifier());
+    final CustomerEntity customerEntity = 
findCustomerEntityOrThrow(executeTaskForCustomerCommand.customerIdentifier());
     final List<TaskInstanceEntity> taskInstanceEntities = 
this.taskInstanceRepository.findByCustomer(customerEntity);
     if (taskInstanceEntities != null) {
       final Optional<TaskInstanceEntity> taskInstanceEntityOptional = 
taskInstanceEntities
@@ -160,4 +159,9 @@ public class TaskAggregate {
       return false;
     }
   }
+
+  private CustomerEntity findCustomerEntityOrThrow(String identifier) {
+    return this.customerRepository.findByIdentifier(identifier)
+        .orElseThrow(() -> ServiceException.notFound("Customer ''{0}'' not 
found", identifier));
+  }
 }
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/repository/CommandRepository.java
 
b/service/src/main/java/io/mifos/customer/service/internal/repository/CommandRepository.java
index 7d0be4f..1d69ea9 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/repository/CommandRepository.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/repository/CommandRepository.java
@@ -17,9 +17,9 @@ package io.mifos.customer.service.internal.repository;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 
-import java.util.List;
+import java.util.stream.Stream;
 
 public interface CommandRepository extends JpaRepository<CommandEntity, Long> {
 
-  List<CommandEntity> findByCustomer(final CustomerEntity customerEntity);
+  Stream<CommandEntity> findByCustomer(final CustomerEntity customerEntity);
 }
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/repository/CustomerRepository.java
 
b/service/src/main/java/io/mifos/customer/service/internal/repository/CustomerRepository.java
index 0a85fa9..61391ad 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/repository/CustomerRepository.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/repository/CustomerRepository.java
@@ -22,6 +22,8 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.Optional;
+
 @Repository
 public interface CustomerRepository extends JpaRepository<CustomerEntity, 
Long> {
 
@@ -31,7 +33,7 @@ public interface CustomerRepository extends 
JpaRepository<CustomerEntity, Long>
   Page<CustomerEntity> 
findByIdentifierContainingOrGivenNameContainingOrSurnameContaining(
       final String identifier, final String givenName, final String surname, 
final Pageable pageable);
 
-  CustomerEntity findByIdentifier(final String identifier);
+  Optional<CustomerEntity> findByIdentifier(final String identifier);
 
   Page<CustomerEntity> findByCurrentStateNot(final String state, final 
Pageable pageable);
 
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/repository/IdentificationCardRepository.java
 
b/service/src/main/java/io/mifos/customer/service/internal/repository/IdentificationCardRepository.java
index 294c249..7903e82 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/repository/IdentificationCardRepository.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/repository/IdentificationCardRepository.java
@@ -20,8 +20,8 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
-import java.util.List;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 @Repository
 public interface IdentificationCardRepository extends 
JpaRepository<IdentificationCardEntity, Long> {
@@ -31,5 +31,5 @@ public interface IdentificationCardRepository extends 
JpaRepository<Identificati
 
   Optional<IdentificationCardEntity> findByNumber(final String number);
 
-  List<IdentificationCardEntity> findByCustomer(final CustomerEntity 
customerEntity);
+  Stream<IdentificationCardEntity> findByCustomer(final CustomerEntity 
customerEntity);
 }
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/service/CustomerService.java
 
b/service/src/main/java/io/mifos/customer/service/internal/service/CustomerService.java
index cc886aa..280b509 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/service/CustomerService.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/service/CustomerService.java
@@ -15,42 +15,14 @@
  */
 package io.mifos.customer.service.internal.service;
 
-import io.mifos.customer.api.v1.domain.Command;
-import io.mifos.customer.api.v1.domain.Customer;
-import io.mifos.customer.api.v1.domain.CustomerPage;
-import io.mifos.customer.api.v1.domain.IdentificationCard;
-import io.mifos.customer.api.v1.domain.IdentificationCardScan;
-import io.mifos.customer.api.v1.domain.ProcessStep;
-import io.mifos.customer.api.v1.domain.TaskDefinition;
+import io.mifos.customer.api.v1.domain.*;
 import io.mifos.customer.catalog.api.v1.domain.Value;
 import io.mifos.customer.catalog.service.internal.repository.FieldEntity;
 import io.mifos.customer.catalog.service.internal.repository.FieldValueEntity;
 import 
io.mifos.customer.catalog.service.internal.repository.FieldValueRepository;
-import io.mifos.customer.service.ServiceConstants;
-import io.mifos.customer.service.internal.mapper.AddressMapper;
-import io.mifos.customer.service.internal.mapper.CommandMapper;
-import io.mifos.customer.service.internal.mapper.ContactDetailMapper;
-import io.mifos.customer.service.internal.mapper.CustomerMapper;
-import io.mifos.customer.service.internal.mapper.IdentificationCardMapper;
-import io.mifos.customer.service.internal.mapper.IdentificationCardScanMapper;
-import io.mifos.customer.service.internal.mapper.TaskDefinitionMapper;
-import io.mifos.customer.service.internal.repository.CommandEntity;
-import io.mifos.customer.service.internal.repository.CommandRepository;
-import io.mifos.customer.service.internal.repository.ContactDetailEntity;
-import io.mifos.customer.service.internal.repository.ContactDetailRepository;
-import io.mifos.customer.service.internal.repository.CustomerEntity;
-import io.mifos.customer.service.internal.repository.CustomerRepository;
-import io.mifos.customer.service.internal.repository.IdentificationCardEntity;
-import 
io.mifos.customer.service.internal.repository.IdentificationCardRepository;
-import 
io.mifos.customer.service.internal.repository.IdentificationCardScanEntity;
-import 
io.mifos.customer.service.internal.repository.IdentificationCardScanRepository;
-import io.mifos.customer.service.internal.repository.PortraitEntity;
-import io.mifos.customer.service.internal.repository.PortraitRepository;
-import io.mifos.customer.service.internal.repository.TaskDefinitionRepository;
-import io.mifos.customer.service.internal.repository.TaskInstanceRepository;
-import org.slf4j.Logger;
+import io.mifos.customer.service.internal.mapper.*;
+import io.mifos.customer.service.internal.repository.*;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
@@ -60,11 +32,11 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @Service
 public class CustomerService {
 
-  private final Logger logger;
   private final CustomerRepository customerRepository;
   private final IdentificationCardRepository identificationCardRepository;
   private final IdentificationCardScanRepository 
identificationCardScanRepository;
@@ -76,8 +48,7 @@ public class CustomerService {
   private final TaskInstanceRepository taskInstanceRepository;
 
   @Autowired
-  public CustomerService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger 
logger,
-                         final CustomerRepository customerRepository,
+  public CustomerService(final CustomerRepository customerRepository,
                          final IdentificationCardRepository 
identificationCardRepository,
                          final IdentificationCardScanRepository 
identificationCardScanRepository,
                          final PortraitRepository portraitRepository,
@@ -87,7 +58,6 @@ public class CustomerService {
                          final TaskDefinitionRepository 
taskDefinitionRepository,
                          final TaskInstanceRepository taskInstanceRepository) {
     super();
-    this.logger = logger;
     this.customerRepository = customerRepository;
     this.identificationCardRepository = identificationCardRepository;
     this.identificationCardScanRepository = identificationCardScanRepository;
@@ -103,10 +73,6 @@ public class CustomerService {
     return this.customerRepository.existsByIdentifier(identifier);
   }
 
-  public Boolean portraitExists(final String identifier) {
-    return this.portraitRepository.existsByIdentifier(identifier);
-  }
-
   public Boolean identificationCardExists(final String number) {
     return this.identificationCardRepository.existsByNumber(number);
   }
@@ -118,41 +84,39 @@ public class CustomerService {
   }
 
   public Optional<Customer> findCustomer(final String identifier) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(identifier);
-    if (customerEntity != null) {
-      final Customer customer = CustomerMapper.map(customerEntity);
-      customer.setAddress(AddressMapper.map(customerEntity.getAddress()));
-
-      final List<ContactDetailEntity> contactDetailEntities = 
this.contactDetailRepository.findByCustomer(customerEntity);
-      if (contactDetailEntities != null) {
-        customer.setContactDetails(
-            contactDetailEntities
-                .stream()
-                  .map(ContactDetailMapper::map)
-                  .collect(Collectors.toList())
-        );
-      }
-
-      final List<FieldValueEntity> fieldValueEntities = 
this.fieldValueRepository.findByCustomer(customerEntity);
-      if (fieldValueEntities != null) {
-        customer.setCustomValues(
-            fieldValueEntities
-                .stream()
-                .map(fieldValueEntity -> {
-                  final Value value = new Value();
-                  value.setValue(fieldValueEntity.getValue());
-                  final FieldEntity fieldEntity = fieldValueEntity.getField();
-                  
value.setCatalogIdentifier(fieldEntity.getCatalog().getIdentifier());
-                  value.setFieldIdentifier(fieldEntity.getIdentifier());
-                  return value;
-                }).collect(Collectors.toList())
-        );
-      }
-
-      return Optional.of(customer);
-    } else {
-      return Optional.empty();
-    }
+    return customerRepository.findByIdentifier(identifier)
+        .map(customerEntity -> {
+          final Customer customer = CustomerMapper.map(customerEntity);
+          customer.setAddress(AddressMapper.map(customerEntity.getAddress()));
+
+          final List<ContactDetailEntity> contactDetailEntities = 
this.contactDetailRepository.findByCustomer(customerEntity);
+          if (contactDetailEntities != null) {
+            customer.setContactDetails(
+                contactDetailEntities
+                    .stream()
+                    .map(ContactDetailMapper::map)
+                    .collect(Collectors.toList())
+            );
+          }
+
+          final List<FieldValueEntity> fieldValueEntities = 
this.fieldValueRepository.findByCustomer(customerEntity);
+          if (fieldValueEntities != null) {
+            customer.setCustomValues(
+                fieldValueEntities
+                    .stream()
+                    .map(fieldValueEntity -> {
+                      final Value value = new Value();
+                      value.setValue(fieldValueEntity.getValue());
+                      final FieldEntity fieldEntity = 
fieldValueEntity.getField();
+                      
value.setCatalogIdentifier(fieldEntity.getCatalog().getIdentifier());
+                      value.setFieldIdentifier(fieldEntity.getIdentifier());
+                      return value;
+                    }).collect(Collectors.toList())
+            );
+          }
+
+          return customer;
+        });
   }
 
   public CustomerPage fetchCustomer(final String term, final Boolean 
includeClosed, final Pageable pageable) {
@@ -186,31 +150,23 @@ public class CustomerService {
     return customerPage;
   }
 
-  public final List<Command> fetchCommandsByCustomer(final String identifier) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(identifier);
-    final List<CommandEntity> commands = 
this.commandRepository.findByCustomer(customerEntity);
-    if (commands != null) {
-      return 
commands.stream().map(CommandMapper::map).collect(Collectors.toList());
-    } else {
-      return Collections.emptyList();
-    }
+  public final Stream<Command> fetchCommandsByCustomer(final String 
identifier) {
+    return customerRepository.findByIdentifier(identifier)
+        .map(commandRepository::findByCustomer)
+        .orElse(Stream.empty())
+        .map(CommandMapper::map);
   }
 
-  public final PortraitEntity findPortrait(final String identifier) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(identifier);
-
-    return this.portraitRepository.findByCustomer(customerEntity);
+  public final Optional<PortraitEntity> findPortrait(final String identifier) {
+    return customerRepository.findByIdentifier(identifier)
+        .map(portraitRepository::findByCustomer);
   }
 
-  public final List<IdentificationCard> 
fetchIdentificationCardsByCustomer(final String identifier) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(identifier);
-    final List<IdentificationCardEntity> identificationCards = 
this.identificationCardRepository.findByCustomer(customerEntity);
-
-    if (identificationCards != null) {
-      return 
identificationCards.stream().map(IdentificationCardMapper::map).collect(Collectors.toList());
-    } else {
-      return Collections.emptyList();
-    }
+  public final Stream<IdentificationCard> 
fetchIdentificationCardsByCustomer(final String identifier) {
+    return customerRepository.findByIdentifier(identifier)
+        .map(identificationCardRepository::findByCustomer)
+        .orElse(Stream.empty())
+        .map(IdentificationCardMapper::map);
   }
 
   public Optional<IdentificationCard> findIdentificationCard(final String 
number) {
@@ -229,8 +185,7 @@ public class CustomerService {
 
   private Optional<IdentificationCardScanEntity> 
findIdentificationCardEntity(final String number, final String identifier) {
     final Optional<IdentificationCardEntity> cardEntity = 
this.identificationCardRepository.findByNumber(number);
-    final Optional<IdentificationCardScanEntity> cardScanEntity = 
cardEntity.flatMap(card -> 
this.identificationCardScanRepository.findByIdentifierAndIdentificationCard(identifier,
 card));
-    return cardScanEntity;
+    return cardEntity.flatMap(card -> 
this.identificationCardScanRepository.findByIdentifierAndIdentificationCard(identifier,
 card));
   }
 
   public Optional<IdentificationCardScan> findIdentificationCardScan(final 
String number, final String identifier) {
@@ -242,29 +197,32 @@ public class CustomerService {
   }
 
   public List<ProcessStep> getProcessSteps(final String customerIdentifier) {
-    final ArrayList<ProcessStep> processSteps = new ArrayList<>();
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(customerIdentifier);
-
-    final Customer.State state = 
Customer.State.valueOf(customerEntity.getCurrentState());
-    switch (state) {
-      case PENDING:
-        processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.ACTIVATE));
-        processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.CLOSE));
-        break;
-      case ACTIVE:
-        processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.LOCK));
-        processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.CLOSE));
-        break;
-      case LOCKED:
-        processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.UNLOCK));
-        processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.CLOSE));
-        break;
-      case CLOSED:
-        processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.REOPEN));
-        break;
-    }
-
-    return processSteps;
+    return customerRepository.findByIdentifier(customerIdentifier)
+        .map(customerEntity -> {
+          final List<ProcessStep> processSteps = new ArrayList<>();
+
+          final Customer.State state = 
Customer.State.valueOf(customerEntity.getCurrentState());
+          switch (state) {
+            case PENDING:
+              processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.ACTIVATE));
+              processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.CLOSE));
+              break;
+            case ACTIVE:
+              processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.LOCK));
+              processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.CLOSE));
+              break;
+            case LOCKED:
+              processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.UNLOCK));
+              processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.CLOSE));
+              break;
+            case CLOSED:
+              processSteps.add(this.buildProcessStep(customerEntity, 
Command.Action.REOPEN));
+              break;
+          }
+
+          return processSteps;
+        })
+        .orElse(Collections.emptyList());
   }
 
   private ProcessStep buildProcessStep(final CustomerEntity customerEntity, 
final Command.Action action) {
@@ -276,14 +234,13 @@ public class CustomerService {
 
     final ArrayList<TaskDefinition> taskDefinitions = new ArrayList<>();
     
this.taskDefinitionRepository.findByAssignedCommandsContaining(action.name())
-        .forEach(taskDefinitionEntity -> {
-          
this.taskInstanceRepository.findByCustomerAndTaskDefinition(customerEntity, 
taskDefinitionEntity)
-              .forEach(taskInstanceEntity -> {
-                if (taskInstanceEntity.getExecutedBy() == null) {
-                  
taskDefinitions.add(TaskDefinitionMapper.map(taskDefinitionEntity));
-                }
-              });
-        });
+        .forEach(taskDefinitionEntity ->
+            
this.taskInstanceRepository.findByCustomerAndTaskDefinition(customerEntity, 
taskDefinitionEntity)
+            .forEach(taskInstanceEntity -> {
+              if (taskInstanceEntity.getExecutedBy() == null) {
+                
taskDefinitions.add(TaskDefinitionMapper.map(taskDefinitionEntity));
+              }
+            }));
     processStep.setTaskDefinitions(taskDefinitions);
 
     return processStep;
diff --git 
a/service/src/main/java/io/mifos/customer/service/internal/service/TaskService.java
 
b/service/src/main/java/io/mifos/customer/service/internal/service/TaskService.java
index 66132fc..a751601 100644
--- 
a/service/src/main/java/io/mifos/customer/service/internal/service/TaskService.java
+++ 
b/service/src/main/java/io/mifos/customer/service/internal/service/TaskService.java
@@ -17,7 +17,6 @@ package io.mifos.customer.service.internal.service;
 
 import io.mifos.customer.api.v1.domain.TaskDefinition;
 import io.mifos.customer.service.internal.mapper.TaskDefinitionMapper;
-import io.mifos.customer.service.internal.repository.CustomerEntity;
 import io.mifos.customer.service.internal.repository.CustomerRepository;
 import io.mifos.customer.service.internal.repository.TaskDefinitionEntity;
 import io.mifos.customer.service.internal.repository.TaskDefinitionRepository;
@@ -25,6 +24,7 @@ import 
io.mifos.customer.service.internal.repository.TaskInstanceRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -67,8 +67,9 @@ public class TaskService {
   }
 
   public List<TaskDefinition> findTasksByCustomer(final String 
customerIdentifier, Boolean includeExecuted) {
-    final CustomerEntity customerEntity = 
this.customerRepository.findByIdentifier(customerIdentifier);
-    return this.taskInstanceRepository.findByCustomer(customerEntity)
+    return customerRepository.findByIdentifier(customerIdentifier)
+        .map(taskInstanceRepository::findByCustomer)
+        .orElse(Collections.emptyList())
         .stream()
         .filter(taskInstanceEntity -> (includeExecuted ? true : 
taskInstanceEntity.getExecutedBy() == null))
         .map(taskInstanceEntity -> 
TaskDefinitionMapper.map(taskInstanceEntity.getTaskDefinition()))
diff --git 
a/service/src/main/java/io/mifos/customer/service/rest/controller/CustomerRestController.java
 
b/service/src/main/java/io/mifos/customer/service/rest/controller/CustomerRestController.java
index d07124e..d5010f5 100644
--- 
a/service/src/main/java/io/mifos/customer/service/rest/controller/CustomerRestController.java
+++ 
b/service/src/main/java/io/mifos/customer/service/rest/controller/CustomerRestController.java
@@ -79,6 +79,8 @@ import javax.validation.Valid;
 import javax.validation.constraints.Size;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @RestController
 @RequestMapping("/")
@@ -267,7 +269,7 @@ public class CustomerRestController {
   @ResponseBody
   ResponseEntity<List<Command>> 
fetchCustomerCommands(@PathVariable("identifier") final String identifier) {
     if (this.customerService.customerExists(identifier)) {
-      return 
ResponseEntity.ok(this.customerService.fetchCommandsByCustomer(identifier));
+      return 
ResponseEntity.ok(this.customerService.fetchCommandsByCustomer(identifier).collect(Collectors.toList()));
     } else {
       throw ServiceException.notFound("Customer {0} not found.", identifier);
     }
@@ -315,8 +317,8 @@ public class CustomerRestController {
         final TaskDefinition taskDefinition = optionalTaskDefinition.get();
         switch (TaskDefinition.Type.valueOf(taskDefinition.getType())) {
           case ID_CARD:
-            final List<IdentificationCard> identificationCards = 
this.customerService.fetchIdentificationCardsByCustomer(identifier);
-            if (identificationCards.isEmpty()) {
+            final Stream<IdentificationCard> identificationCards = 
this.customerService.fetchIdentificationCardsByCustomer(identifier);
+            if (!identificationCards.findAny().isPresent()) {
               throw ServiceException.conflict("No identification cards for 
customer found.");
             }
             break;
@@ -401,7 +403,7 @@ public class CustomerRestController {
   )
   public @ResponseBody ResponseEntity<List<IdentificationCard>> 
fetchIdentificationCards(@PathVariable("identifier") final String identifier) {
     this.throwIfCustomerNotExists(identifier);
-    return 
ResponseEntity.ok(this.customerService.fetchIdentificationCardsByCustomer(identifier));
+    return 
ResponseEntity.ok(this.customerService.fetchIdentificationCardsByCustomer(identifier).collect(Collectors.toList()));
   }
 
   @Permittable(value = AcceptedTokenType.TENANT, groupId = 
PermittableGroupIds.IDENTIFICATIONS)
@@ -612,9 +614,8 @@ public class CustomerRestController {
       consumes = MediaType.ALL_VALUE
   )
   public ResponseEntity<byte[]> getPortrait(@PathVariable("identifier") final 
String identifier) {
-    this.throwIfPortraitNotExists(identifier);
-
-    final PortraitEntity portrait = 
this.customerService.findPortrait(identifier);
+    final PortraitEntity portrait = 
this.customerService.findPortrait(identifier)
+        .orElseThrow(() -> ServiceException.notFound("Portrait for Customer 
''{0}'' not found.", identifier));
 
     return ResponseEntity
             .ok()
@@ -759,12 +760,6 @@ public class CustomerRestController {
     }
   }
 
-  private void throwIfPortraitNotExists(final String identifier) {
-    if (!this.customerService.portraitExists(identifier)) {
-      throw ServiceException.notFound("Portrait for Customer {0} not found.", 
identifier);
-    }
-  }
-
   private void throwIfIdentificationCardNotExists(final String number) {
     if (!this.customerService.identificationCardExists(number)) {
       throw ServiceException.notFound("Identification card {0} not found.", 
number);

-- 
To stop receiving notification emails like this one, please contact
my...@apache.org.

Reply via email to