/* * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v2.0 which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v20.html * * SPDX-License-Identifier: EPL-2.0 * * Copyright Contributors to the Zowe Project. */ package org.zowe.apiml.client.api; import org.zowe.apiml.client.exception.PetIdMismatchException; import org.zowe.apiml.client.exception.PetNotFoundException; import org.zowe.apiml.message.api.ApiMessage; import org.zowe.apiml.message.api.ApiMessageView; import org.zowe.apiml.message.core.Message; import org.zowe.apiml.message.core.MessageService; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; import lombok.RequiredArgsConstructor; import org.springframework.beans.TypeMismatchException; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * This class creates responses for exceptional behavior of the PetController */ @ControllerAdvice(assignableTypes = {PetController.class}) @Order(Ordered.HIGHEST_PRECEDENCE) @RequiredArgsConstructor public class PetControllerExceptionHandler { private final MessageService messageService; /** * The handlePetNotFound method creates a response when the pet with a provided ID is not found * * @param exception PetNotFoundException * @return 404 and the message 'Pet with provided ID not found' */ @ExceptionHandler(PetNotFoundException.class) public ResponseEntity<ApiMessageView> handlePetNotFound(PetNotFoundException exception) { Message message = messageService.createMessage("org.zowe.apiml.sampleservice.api.petNotFound", exception.getId()); return ResponseEntity .status(HttpStatus.NOT_FOUND) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(message.mapToView()); } /** * The handleIdMismatch method creates a response when the pet ID in the request body and the pet ID in the URL are different * * @param exception PetIdMismatchException * @return 400 and the message 'Invalid ID' */ @ExceptionHandler(PetIdMismatchException.class) public ResponseEntity<ApiMessageView> handleIdMismatch(PetIdMismatchException exception) { Message message = messageService.createMessage("org.zowe.apiml.sampleservice.api.petIdMismatchException", exception.getPathId(), exception.getBodyId()); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(message.mapToView()); } /** * The handleIdTypeMismatch method creates a response when the pet ID is invalid * * @param exception TypeMismatchException * @return 400 and the message 'The pet ID is invalid: it is not an integer' */ @ExceptionHandler(TypeMismatchException.class) public ResponseEntity<ApiMessageView> handleIdTypeMismatch(TypeMismatchException exception) { Message message = messageService.createMessage("org.zowe.apiml.sampleservice.api.petIdTypeMismatch", exception.getValue()); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(message.mapToView()); } /** * The handleMethodArgumentNotValid method creates a response with a list of messages that contains the fields with errors * * @param exception MethodArgumentNotValidException * @return 400 and a list of messages with invalid fields */ @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ApiMessageView> handleMethodArgumentNotValid(MethodArgumentNotValidException exception) { List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors(); List<Object[]> messages = new ArrayList<>(); for (FieldError fieldError : fieldErrors) { Object[] messageFields = new Object[3]; messageFields[0] = fieldError.getField(); messageFields[1] = fieldError.getRejectedValue(); messageFields[2] = fieldError.getDefaultMessage(); messages.add(messageFields); } List<ApiMessage> listApiMessage = messageService .createMessage("org.zowe.apiml.sampleservice.api.petMethodArgumentNotValid", messages) .stream() .map(Message::mapToApiMessage) .collect(Collectors.toList()); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(new ApiMessageView(listApiMessage)); } /** * The handleUnrecognizedProperty method creates a response when the request body does not correspond to the model object * * @param exception UnrecognizedPropertyException * @return 400 and the message 'Unrecognized field '%s'' */ @ExceptionHandler(UnrecognizedPropertyException.class) public ResponseEntity<ApiMessageView> handleUnrecognizedProperty(UnrecognizedPropertyException exception) { Message message = messageService.createMessage("org.zowe.apiml.sampleservice.api.petUnrecognizedProperty", exception.getPropertyName()); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(message.mapToView()); } /** * The jsonParseException method creates a response when the provided body is not a valid JSON * * @param exception JsonParseException * @return 400 and the message 'Request is not valid JSON' */ @ExceptionHandler(JsonParseException.class) public ResponseEntity<ApiMessageView> jsonParseException(JsonParseException exception) { Message message = messageService.createMessage("org.zowe.apiml.sampleservice.api.jsonParseException", exception.getMessage()); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(message.mapToView()); } /** * The handleInvalidFormatException method creates a response when the field is in the wrong format * * @param exception InvalidFormatException * @return 400 and the message 'Field name has wrong format' */ @ExceptionHandler(InvalidFormatException.class) public ResponseEntity<ApiMessageView> handleInvalidFormatException(InvalidFormatException exception) { String fieldName = exception.getPath().get(0).getFieldName(); Message message = messageService.createMessage("org.zowe.apiml.sampleservice.api.petInvalidFormatException", fieldName); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(message.mapToView()); } }