Skip to content

Commit

Permalink
Add exceptions (#405)
Browse files Browse the repository at this point in the history
* Add first exception

* Start using global exception in core service

* Configure global exception in user service
  • Loading branch information
tschaffter committed Jul 5, 2022
1 parent a847b47 commit 1ffb7db
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.sagebionetworks.challenge.exception;

import org.sagebionetworks.challenge.util.exception.SimpleChallengeGlobalException;

public class EntityNotFoundException extends SimpleChallengeGlobalException {
public EntityNotFoundException() {
super("Requested entity not present in the DB.", GlobalErrorCode.ERROR_ENTITY_NOT_FOUND);
}

public EntityNotFoundException(String message) {
super(message, GlobalErrorCode.ERROR_ENTITY_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.sagebionetworks.challenge.exception;

public class GlobalErrorCode {
public static final String ERROR_ENTITY_NOT_FOUND = "CHALLENGE-CORE-SERVICE-1000";
public static final String INSUFFICIENT_FUNDS = "CHALLENGE-CORE-SERVICE-1001";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.sagebionetworks.challenge.exception;

import org.sagebionetworks.challenge.util.exception.SimpleChallengeGlobalException;
import org.sagebionetworks.challenge.util.exception.ErrorResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.util.Locale;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(SimpleChallengeGlobalException.class)
protected ResponseEntity handleGlobalException(
SimpleChallengeGlobalException simpleChallengeGlobalException, Locale locale) {
return ResponseEntity.badRequest()
.body(ErrorResponse.builder().code(simpleChallengeGlobalException.getCode())
.message(simpleChallengeGlobalException.getMessage()).build());
}

@ExceptionHandler({Exception.class})
protected ResponseEntity<String> handleException(Exception e, Locale locale) {
return ResponseEntity.badRequest().body("Exception occur inside API " + e);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sagebionetworks.challenge.service;

import org.sagebionetworks.challenge.exception.EntityNotFoundException;
import org.sagebionetworks.challenge.model.dto.User;
import org.sagebionetworks.challenge.model.entity.UserEntity;
import org.sagebionetworks.challenge.model.mapper.UserMapper;
Expand All @@ -19,7 +20,8 @@ public class UserService {
private final UserRepository userRepository;

public User readUser(String identification) {
UserEntity userEntity = userRepository.findByIdentificationNumber(identification).get();
UserEntity userEntity = userRepository.findByIdentificationNumber(identification)
.orElseThrow(EntityNotFoundException::new);
return userMapper.convertToDto(userEntity);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sagebionetworks.challenge.configuration;

import feign.codec.ErrorDecoder;
import org.springframework.cloud.openfeign.FeignClientProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomFeignClientConfiguration extends FeignClientProperties.FeignClientConfiguration {

@Bean
public ErrorDecoder errorDecoder() {
return new CustomFeignErrorDecoder();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.sagebionetworks.challenge.configuration;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Response;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.sagebionetworks.challenge.exception.SimpleChallengeGlobalException;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;

@Slf4j
public class CustomFeignErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {

SimpleChallengeGlobalException simpleChallengeGlobalException =
extractChallengeCoreGlobalException(response);

switch (response.status()) {
case 400:
log.error("Error in request went through feign client {} ",
simpleChallengeGlobalException.getMessage() + " - "
+ simpleChallengeGlobalException.getCode());
return simpleChallengeGlobalException;
case 401:
log.error("Unauthorized Request Through Feign");
return new Exception("Unauthorized Request Through Feign");
case 404:
log.error("Unidentified Request Through Feign");
return new Exception("Unidentified Request Through Feign");
default:
log.error("Error in request went through feign client");
return new Exception("Common Feign Exception");
}

}

private SimpleChallengeGlobalException extractChallengeCoreGlobalException(Response response) {
SimpleChallengeGlobalException exceptionMessage = null;
Reader reader = null;
// capturing error message from response body.
try {
reader = response.body().asReader(StandardCharsets.UTF_8);
String result = IOUtils.toString(reader);
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
exceptionMessage = mapper.readValue(result, SimpleChallengeGlobalException.class);
} catch (IOException e) {
log.error("IO Exception on reading exception message feign client" + e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
log.error("IO Exception on reading exception message feign client" + e);
}
}
return exceptionMessage;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package org.sagebionetworks.challenge.service.rest;

import org.sagebionetworks.challenge.configuration.CustomFeignClientConfiguration;
import org.sagebionetworks.challenge.model.rest.response.UserResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(name = "challenge-core-service")
@FeignClient(name = "challenge-core-service", configuration = CustomFeignClientConfiguration.class)
public interface ChallengeCoreRestClient {

@RequestMapping(method = RequestMethod.GET, value = "/api/v1/user/{identification}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.sagebionetworks.challenge.util.exception;

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Builder
public class ErrorResponse {
private String code;
private String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.sagebionetworks.challenge.util.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class SimpleChallengeGlobalException extends RuntimeException {

private String code;
private String message;

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

0 comments on commit 1ffb7db

Please sign in to comment.