Commit 9980b7fd authored by Alex Segers's avatar Alex Segers

[AFP-91] 🥅 Integrate custom exceptions to 'ManagerController' (@asegers)

parent f6a7821d
package com.afp.ordermanagement.controller; package com.afp.ordermanagement.controller;
import com.afp.ordermanagement.exception.BadAccessTokenException;
import com.afp.ordermanagement.exception.EntityNotFoundException;
import com.afp.ordermanagement.model.Manager; import com.afp.ordermanagement.model.Manager;
import com.afp.ordermanagement.model.Order; import com.afp.ordermanagement.service.ManagerService;
import com.afp.ordermanagement.repository.ManagerRepository; import com.afp.ordermanagement.service.ManagerTokenVerifier;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.validation.Valid;
@Validated
@RestController @RestController
@RequestMapping("/api") @RequestMapping("/api/managers/")
public class ManagerController { public class ManagerController {
@Autowired @Autowired
ManagerRepository managerRepository; ManagerService managerService;
@GetMapping("/manager") @GetMapping("/")
public Flux<Manager> getAllManagers() { public Flux<Manager> getAllManagers() {
System.out.println("here"); return managerService.getAll();
Flux<Manager> managerFlux = managerRepository.findAll();
return managerFlux;
} }
@PostMapping("/")
@ResponseStatus(HttpStatus.CREATED)
public Mono<Manager> createManager(@Valid @RequestBody Manager newManager) {
return managerService.create(newManager);
}
@PostMapping("/auth")
public Mono<Manager> getOrCreateManagerFromAccessToken(@RequestHeader(name = "Authorization") String tokenHeader) {
String tokenStr = tokenHeader.replace("Bearer ", "");
if (!ManagerTokenVerifier.isTokenValid(tokenStr))
return Mono.error(new BadAccessTokenException());
Manager managerPayload = ManagerTokenVerifier.createManager(tokenStr);
return managerService.getByEmail(managerPayload.getEmail())
.switchIfEmpty(managerService.create(managerPayload));
}
@GetMapping("/{uuid}")
public Mono<Manager> getManagerById(@PathVariable String uuid) {
return managerService.getById(uuid)
.switchIfEmpty(Mono.error(new EntityNotFoundException(uuid, Manager.class)));
}
@PatchMapping("/{uuid}")
public Mono<Manager> updateManagerById(@PathVariable String uuid, @RequestBody @Valid Manager managerUpdates) {
return managerService.updateById(uuid, managerUpdates);
}
@DeleteMapping("/{uuid}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public Mono<Void> deleteManagerById(@PathVariable String uuid) {
return managerService.getById(uuid)
.switchIfEmpty(Mono.error(new EntityNotFoundException(uuid, Manager.class)))
.flatMap(managerService::delete);
}
} }
package com.afp.ordermanagement.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public class BadAccessTokenException extends RuntimeException {
public BadAccessTokenException() {
super("Invalid access token");
}
}
package com.afp.ordermanagement.exception;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ServerWebExchange;
@ControllerAdvice
@RequiredArgsConstructor
public class ControllerExceptionAdvice {
@ExceptionHandler(BadAccessTokenException.class)
public ResponseEntity<ErrorResponse> handleBadAccessTokenException(RuntimeException exc, ServerWebExchange exchange) {
final HttpStatus status = HttpStatus.UNAUTHORIZED;
final ServerHttpRequest request = exchange.getRequest();
return new ResponseEntity<>(new ErrorResponse(
status.value(),
request.getPath().value(),
status.getReasonPhrase(),
exc.getMessage()
), status);
}
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<ErrorResponse> handleEntityNotFoundException(RuntimeException exc, ServerWebExchange exchange) {
final HttpStatus status = HttpStatus.NOT_FOUND;
final ServerHttpRequest request = exchange.getRequest();
return new ResponseEntity<>(new ErrorResponse(
status.value(),
request.getPath().value(),
status.getReasonPhrase(),
exc.getMessage()
), status);
}
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException exc, ServerWebExchange exchange) {
final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
final ServerHttpRequest request = exchange.getRequest();
return new ResponseEntity<>(new ErrorResponse(
status.value(),
request.getPath().value(),
status.getReasonPhrase(),
exc.getMessage()
), status);
}
@ExceptionHandler(WebExchangeBindException.class)
public ResponseEntity<ErrorResponse> webExchangeBindException(WebExchangeBindException exc, ServerWebExchange exchange) {
final HttpStatus status = exc.getStatus();
final ServerHttpRequest request = exchange.getRequest();
if (InvalidEntityResponse.isEntityValid(exc.getTarget())) {
return new ResponseEntity<>(new ErrorResponse(
status.value(),
request.getPath().value(),
status.getReasonPhrase(),
exc.getMessage()
), status);
}
return new ResponseEntity<>(new InvalidEntityResponse(
status.value(),
request.getPath().value(),
status.getReasonPhrase(),
"Validation failed",
exc.getTarget()
), status);
}
}
package com.afp.ordermanagement.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class EntityNotFoundException extends RuntimeException {
public EntityNotFoundException(String badUuid, Class entityClass) {
super(String.format("Could not find a %s with the id '%s'", entityClass.getName(), badUuid));
}
}
package com.afp.ordermanagement.exception;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import java.time.Instant;
@Data
@RequiredArgsConstructor
public class ErrorResponse {
public final Integer status;
public final String path, error, message;
public String timestamp = Instant.now().toString();
}
package com.afp.ordermanagement.exception;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class InvalidEntityResponse extends ErrorResponse {
public List<Map<String, String>> fieldErrors;
public InvalidEntityResponse(Integer status, String path, String type, String message, Object entity) {
super(status, path, type, message);
this.fieldErrors = InvalidEntityResponse.parseViolations(entity);
}
public static boolean isEntityValid(Object entity) {
return validator.validate(entity).isEmpty();
}
static private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
static private List<Map<String, String>> parseViolations(Object entity) {
List<Map<String, String>> fieldErrors = new ArrayList<>();
for (ConstraintViolation<Object> cv : validator.validate(entity)) {
Map<String, String> errorMap = new HashMap<String, String>() {{
put("field", cv.getPropertyPath().toString());
put("message", cv.getMessage());
}};
fieldErrors.add(errorMap);
}
return fieldErrors;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment