Home > front end >  Custom Exception not thrown in controller-method when no data is found in database
Custom Exception not thrown in controller-method when no data is found in database

Time:04-03

My controller always give Internal server error whenever my condition fail, and are suppose to throw custom exception ResourceNotFoundException. When I call account/1-endpoint (no account with id 1 in database) I expect an ResourceNotFoundException, but instead I get Internal server Error.. I do not understand why ResourceNotFoundException is not thrown, I watched several youtube tutorials on the topic. Please help by providing possible solutions.

My model classes are

    package com.bank2.Model;
    
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    
    import org.hibernate.annotations.Proxy;
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    
    
    @Entity
    @javax.persistence.Table(name="Account")
    @Proxy(lazy = false)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Account {
    
        
        
        @Id
        int accountNumber;
        @Column(name="balance")
        Double balance;
        @Column(name="accountType")
        String accountType;
        
    public Account() {
            super();
       }
     
    
        @Override
    public String toString() {
        return "Account [accountNumber="   accountNumber   ", balance="   balance   ", accountType="   accountType   "]";
    }
    
        public int getAccountNumber() {
            return accountNumber;
        }
    
    
    
        public void setAccountNumber(int accountNumber) {
            this.accountNumber = accountNumber;
        }
    
    
    
        public Double getBalance() {
            return balance;
        }
    
    
    
        public void setBalance(Double balance) {
            this.balance = balance;
        }
    
    
    
        public String getAccountType() {
            return accountType;
        }
    
    
    
        public void setAccountType(String accountType) {
            this.accountType = accountType;
        }
    
    
    
    
        public Account(int accountNumber, Double balance, String accountType) {
            super();
            this.accountNumber = accountNumber;
            this.balance = balance;
            this.accountType = accountType;
        }
    
        
    }
    package com.bank2.Model;
    
    import java.util.List;
    
    
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    import org.hibernate.annotations.Proxy;
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    
    
    @Entity
    @Table(name="Customer")
    @Proxy(lazy = false)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Customer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        Integer customerId;
        @Column(name="customerName")
        String customerName;
    
        @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,targetEntity = Account.class)
        @JoinColumn(name = "ca_fk",referencedColumnName ="customerId")
        private List<Account> accounts;
    
        public Customer() {
            super();
        }
    
        public Customer(Integer customerId, String customerName, List<Account> accounts) {
            super();
            this.customerId = customerId;
            this.customerName = customerName;
            this.accounts = accounts;
        }
    
        public Integer getCustomerId() {
            return customerId;
        }
    
        public void setCustomerId(Integer customerId) {
            this.customerId = customerId;
        }
    
        public String getCustomerName() {
            return customerName;
        }
    
        public void setCustomerName(String customerName) {
            this.customerName = customerName;
        }
    
        public List<Account> getAccount() {
            return accounts;
        }
    
        public void setAccount(List<Account> accounts) {
            this.accounts = accounts;
        }
    
        @Override
        public String toString() {
            return "Customer [customerId="   customerId   ", customerName="   customerName   ", accounts="   accounts   "]";
        }
        
        
        
        
    }

My service classes are

    package com.bank2.ServiceImpl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.bank2.Model.Customer;
    import com.bank2.repository.CustomerRepository;
    
    @Service
    public class CustomerService  {
    
        @Autowired
        CustomerRepository customerRepository;
        
        public Customer customerCreate(Customer customer) {
           Customer x= customerRepository.save(customer);
           return x;
        }
    
    }
    
    package com.bank2.ServiceImpl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.bank2.Model.Account;
    import com.bank2.repository.AccountRepository;
    
    @Service
    public class AccountService {
        
        @Autowired
        AccountRepository accountRepository;
    
        public Account findAccountById(int accountNumber) {
                
                return  accountRepository.getById(accountNumber);
            }
    
        
        
        
    }

my controller class are

    package com.bank2.controller;
    
    import java.util.Optional;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.bank2.Exception.ResourceNotFoundException;
    import com.bank2.Model.Account;
    import com.bank2.ServiceImpl.AccountService;
    
    @RestController
    @RequestMapping("/account")
    public class AccountController {
    
        @Autowired
        AccountService accountService;
        
        @GetMapping("/{accountNumber}")
            public ResponseEntity<?> getAccountById(@PathVariable("accountNumber") int accountNumber){
                Account acc=accountService.findAccountById(accountNumber);
                if(acc==null) {
                    throw new ResourceNotFoundException("Account [accountNumber=" accountNumber "] can't be found");
                }else {
                    return new ResponseEntity<>(acc,HttpStatus.FOUND);
                }
                
    
        }
        
    package com.bank2.controller;
    
    import java.util.Optional;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.bank2.Exception.ResourceNotFoundException;
    import com.bank2.Model.Customer;
    import com.bank2.ServiceImpl.CustomerService;
    
    @RestController
    @RequestMapping("/customer")
    public class CustomerController {
    
        @Autowired
        CustomerService customerService;
        
        @PostMapping("/createCust")
            public ResponseEntity<?> CreateCustomer(@RequestBody Customer customer){
            Customer cus=customerService.customerCreate(customer);
            Optional<Customer> cus1 = Optional.ofNullable(cus);
            if(cus1.isEmpty()) {
                          throw new ResourceNotFoundException("customer not created!!");
                }else {
                     return new ResponseEntity<>(cus,HttpStatus.CREATED);
                   }
             }
    
    }
    

my expection classes are

    package com.bank2.Exception;
    
    import java.time.LocalDateTime;
    import java.util.List;
    
    import org.springframework.http.HttpStatus;
    
    
    
    
    public class ApiErrors {
    
        String message;
        List<String> details;
        HttpStatus status;
        LocalDateTime timestamp;
        public String getMessage() {
            return message;
        }
        public void setMessage(String message) {
            this.message = message;
        }
        public List<String> getDetails() {
            return details;
        }
        public void setDetails(List<String> details) {
            this.details = details;
        }
        public HttpStatus getStatus() {
            return status;
        }
        public void setStatus(HttpStatus status) {
            this.status = status;
        }
        public LocalDateTime getTimestamp() {
            return timestamp;
        }
        public void setTimestamp(LocalDateTime timestamp) {
            this.timestamp = timestamp;
        }
        public ApiErrors() {
            super();
            // TODO Auto-generated constructor stub
        }
        public ApiErrors(String message, List<String> details, HttpStatus status, LocalDateTime timestamp) {
            super();
            this.message = message;
            this.details = details;
            this.status = status;
            this.timestamp = timestamp;
        }
        @Override
        public String toString() {
            return "ApiErrors [message="   message   ", details="   details   ", status="   status   ", timestamp="
                      timestamp   "]";
        }
            
        
    }
    package com.bank2.Exception;
    
    public class ResourceNotFoundException extends RuntimeException{
    
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
    
        public ResourceNotFoundException() {
            super();
        }
    
        public ResourceNotFoundException(String message) {
            super(message);
        }
        
        
        
        
        
    
    }
    
    package com.bank2.Exception;
    
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.beans.TypeMismatchException;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.http.converter.HttpMessageNotReadableException;
    import org.springframework.web.HttpMediaTypeNotSupportedException;
    import org.springframework.web.HttpRequestMethodNotSupportedException;
    import org.springframework.web.bind.MissingPathVariableException;
    import org.springframework.web.bind.MissingServletRequestParameterException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.context.request.WebRequest;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
    
    @ControllerAdvice
    public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
        
        
        @ExceptionHandler(ResourceNotFoundException.class)
        public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundException ex){
            
            String msg=ex.getMessage();
            List<String> details=new ArrayList<>();
            details.add("Resource not found");
            ApiErrors errors=new ApiErrors(msg,details,HttpStatus.BAD_REQUEST,LocalDateTime.now());
            return new ResponseEntity<Object>(errors,HttpStatus.BAD_REQUEST);
        }
        
        @ExceptionHandler(Exception.class)
        public ResponseEntity<Object> handleOther(Exception ex){
            
            String msg=ex.getMessage();
            List<String> details=new ArrayList<>();
            details.add("Other Exceptions");
            ApiErrors errors=new ApiErrors(msg,details,HttpStatus.INTERNAL_SERVER_ERROR,LocalDateTime.now());
            return new ResponseEntity<Object>(errors,HttpStatus.INTERNAL_SERVER_ERROR);
        }
        
        
        
    }
    

This is the Internal server error I have gotten so far in Postman:

    {
        "message": "Unable to find com.bank2.Model.Account with id 1; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.bank2.Model.Account with id 1",
        "details": [
            "Other Exceptions"
        ],
        "status": "INTERNAL_SERVER_ERROR",
        "timestamp": "2022-04-02T22:09:28.0486246"
    }

My repositories are

'''
package com.bank2.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bank2.Model.Account;

@Repository
public interface AccountRepository extends JpaRepository<Account, Integer> {
    
}

'''
'''
package com.bank2.repository;


import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.bank2.Model.Customer;

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
  
    
    
}

'''

CodePudding user response:

From the Documentation JpaRepository.html#getById-ID-

T getById(ID id)

Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is implemented this is very likely to always return an instance and throw an EntityNotFoundException on first access. Some of them will reject invalid identifiers immediately.

The error message you get shows ...nested exception is EntityNotFoundException, so that could be normal...

So you could throw a ResourceNotFoundException in your service when the Account is not found.

 @Service
 public class AccountService {

   public Account findAccountById(int accountNumber) {
      try {
       return  accountRepository.getById(accountNumber);
      } catch(EntityNotFoundException e) {
          throw new ResourceNotFoundException("Account [accountNumber=" accountNumber "] can't be found")
      }
   }
  • Related