Pradeep Virtuele
Pradeep Virtuele

Reputation: 83

How to re-throw the exception in spring boot rest client

I am trying to learn microservices and trying to implement them. In which I have created two applications. Consider application-1 as layer-1 and application-2 as layer-2. I have created the below classes to handle exceptions in both layer-1 and layer-2

ErrorDetails

@AllArgsConstructor
@Getter
@Setter
public class ErrorDetails {
    private Date timestamp;
    private String message;
    private String path;
    private String application;
}

GlobalExceptionHandler

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler{
    
    
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(),ex.getMessage(), request.getDescription(false),"DBLayer");
        return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> globleExcpetionHandler(Exception ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(),ex.getMessage(), request.getDescription(false),"DBLayer");
        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

ResourceNotFoundException

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends Exception {
    
    private static final long serialVersionUID = 1L;

    public ResourceNotFoundException(String message) {
        super(message);
    }
}

I am getting a proper result if the data is available and I am getting proper exception if the data is unavailable in layer-1 like below.

http://localhost:8080/api/company/1000
{
    "timestamp": "2021-11-24T16:33:12.208+00:00",
    "message": "company not found with id 1000",
    "path": "uri=/api/company/1000",
    "application": "DBLayer"
}

In layer-2, I am calling the same service which I am executing in layer-1. I am able to get a proper result if the resource is available, but I am not able to re-throw the same exception with the same response header if the data is unavailable how do I handle this.

public CompanyDto getCompanyById(Long companyId) {      
        log.info(">> Calling get company by id : ");
        final String finalUrl = "http://localhost:8080/api/company/"+companyId;
        ResponseEntity<CompanyDto>  response= restTemplate.exchange(finalUrl, HttpMethod.GET,ResourceUtil.getNewHttpEntity(null), new ParameterizedTypeReference<CompanyDto>() {});
        return response.getBody();
    }

As per the below comments, I tried like below its working fine but is there any better way because I may have to add so much throws at method signature

public CompanyDto getCompanyById(Long companyId) throws JsonMappingException, JsonProcessingException, ResourceNotFoundException {  
    log.info(">> Calling get company by id : "+companyId);
    final String finalUrl = "http://localhost:8080/api/company/"+companyId;
    ResponseEntity<CompanyDto>  response=null;
    try {
        response= restTemplate.exchange(finalUrl, HttpMethod.GET,ResourceUtil.getNewHttpEntity(null), new ParameterizedTypeReference<CompanyDto>() {}); 
    } catch (HttpStatusCodeException e) {
        exceptionCheck(e);
    }       
    return response.getBody();
}

private void exceptionCheck(HttpStatusCodeException e) throws JsonMappingException, JsonProcessingException, ResourceNotFoundException {
    ObjectMapper mapper = new ObjectMapper();
    String responseString=e.getResponseBodyAsString();
    ErrorDetails ed = mapper.readValue(responseString, ErrorDetails.class);
    if(e.getRawStatusCode()==404) {
        throw new ResourceNotFoundException("kjnj");
    }
}

Upvotes: 2

Views: 1358

Answers (1)

Pradeep Virtuele
Pradeep Virtuele

Reputation: 83

In the second layer, we can the exception in the global exception handler class like below

@ExceptionHandler( {HttpClientErrorException.class, HttpStatusCodeException.class, HttpServerErrorException.class})
@ResponseBody
public ResponseEntity<Object> httpClientErrorException(HttpStatusCodeException e) throws IOException {
    BodyBuilder bodyBuilder = ResponseEntity.status(e.getRawStatusCode()).header("X-Backend-Status", String.valueOf(e.getRawStatusCode()));
    if (e.getResponseHeaders().getContentType() != null) {
        bodyBuilder.contentType(e.getResponseHeaders().getContentType());
    }
    return bodyBuilder.body(e.getResponseBodyAsString());
}

Upvotes: 1

Related Questions