自定义异常处理程序未按预期抛出异常

custom Exception Handler not throwing exception as expected

提问人:munmun swami 提问时间:9/8/2023 最后编辑:munmun swami 更新时间:9/9/2023 访问量:217

问:

我的预期输出是:

{
   "message": " Invalid Booking Id ",
  "statusCode": 400
}

我目前的回答是:

{
    "type": "about:blank",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "Failed to write request",
    "instance": "/hotel/booking/1/transaction"
}

这表示 completePayment 方法中发生了未经处理的异常,并且一般错误处理程序正在捕获该异常,从而导致 500 内部服务器错误。

“InvalidPaymentException”问题是由于Spring Boot应用程序中未处理的异常而产生的。在提供的代码中,当付款模式不是“UPI”或“CARD”时,会引发“InvalidPaymentModeException”。但是,未按预期捕获和处理此异常。相反,将调用用于处理意外异常的通用异常处理程序,从而导致 500 内部服务器错误响应。

错误响应 DTO

                @NoArgsConstructor
                @AllArgsConstructor
                public class ErrorResponse {

                    private String message;
                    private int statusCode;

                }

例外

                public class InvalidBookingIdException extends RuntimeException {

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

异常处理程序

                @ControllerAdvice

                public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

                    private static final Logger log = LoggerFactory.getLogger(com.example.bookingservice.ExceptionHandler.CustomExceptionHandler.class);


                    @ExceptionHandler(InvalidPaymentModeException.class)
                    public ResponseEntity<com.example.bookingservice.dto.ErrorResponse> handleInvalidPaymentRequest(InvalidPaymentModeException ex, WebRequest request) {
                        log.error("InvalidPaymentModeException caught: " + ex.getMessage(), ex);

                        com.example.bookingservice.dto.ErrorResponse errorResponse = new com.example.bookingservice.dto.ErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST.value());
                        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
                    }
                }

控制器层

                @RestController
                @RequestMapping(value = "/hotel")
                public class BookingController {


                    @Autowired
                    ModelMapper modelMapper;

                    @Autowired
                    BookingService bookingService;

                    @Autowired
                    RestTemplate restTemplate;

                    @PostMapping(value = "/booking/{id}/transaction", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
                    public ResponseEntity<?> completePayment(@PathVariable(name = "id") int id, @RequestBody TransactionRequestDto transactionRequestDto) {
                        try{
                            // Retrieve the booking based on the provided ID
                            Booking requestedBooking = bookingService.getBookingBasedOnId(id);

                            // Ensure that the transactionRequestDto contains the necessary data
                            System.out.println("Payment Request: " + transactionRequestDto.toString());

                            // Check if the payment mode is valid
                            String paymentMode = transactionRequestDto.getPaymentMode();
                            if (!bookingService.isValidPaymentMode(paymentMode)) {
                                throw new InvalidPaymentModeException("Invalid mode of payment");
                            }

                            // Define the URL for the Payment Service
                            String transactionGet_IdUrl = "http://localhost:8082/payment/transaction";

                            // Make the POST request to the Payment Service
                            ResponseEntity<Integer> transactionResponse = restTemplate.postForEntity(transactionGet_IdUrl, transactionRequestDto, Integer.class);

                            if (transactionResponse.getStatusCode() == HttpStatus.CREATED) {
                                int transactionId = transactionResponse.getBody();
                                System.out.println("Transaction ID: " + transactionId);

                                // Update the booking with the transaction ID
                                requestedBooking.setTransactionId(transactionId);
                                bookingService.updateBooking(id, requestedBooking);

                                // Map the updated booking to a response DTO
                                BookingResponseDto bookingResponseDto = modelMapper.map(requestedBooking, BookingResponseDto.class);

                                return new ResponseEntity<>(bookingResponseDto, HttpStatus.CREATED);
                            } else {
                                // Handle the case where the payment transaction was not successful
                                return ResponseEntity.status(transactionResponse.getStatusCode()).build();
                            }

                        } catch (Exception e){
                            com.example.bookingservice.dto.ErrorResponse errorResponseForOtherExceptions = new com.example.bookingservice.dto.ErrorResponse("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR.value());
                            return new ResponseEntity(errorResponseForOtherExceptions,HttpStatus.INTERNAL_SERVER_ERROR);
                        }
                    }

                }

安慰

Hibernate: insert into booking (aadhar_number,booked_on,from_date,num_of_rooms,room_numbers,room_price,to_date,transaction_id,booking_id) values (?,?,?,?,?,?,?,?,?)
In CrudRepository ,exiting save
In BookingServiceImpls ,exiting createBooking
In BookingController ,exiting createBooking
In BookingController ,entering completePayment
In BookingServiceImpls ,entering getBookingBasedOnId
In CrudRepository ,entering findById
Hibernate: select b1_0.booking_id,b1_0.aadhar_number,b1_0.booked_on,b1_0.from_date,b1_0.num_of_rooms,b1_0.room_numbers,b1_0.room_price,b1_0.to_date,b1_0.transaction_id from booking b1_0 where b1_0.booking_id=?
In CrudRepository ,exiting findById
In BookingServiceImpls ,exiting getBookingBasedOnId
Payment Request: TransactionRequestDto(paymentMode=other, bookingId=3, upiId=upi details, cardNumber=65757668687)
In BookingServiceImpls ,entering isValidPaymentMode
In BookingServiceImpls ,exiting isValidPaymentMode
In BookingController ,exiting completePayment
Spring-Boot 异常 控制器 运行时异常

评论

0赞 Andrei Lisa 9/8/2023
如果您要从中删除它是否按预期工作?extends ResponseEntityExceptionHandlerCustomExceptionHandler
0赞 munmun swami 9/8/2023
@AndreiLisa还是一样的回应{ "timestamp": "2023-09-08T10:44:13.800+00:00", "status": 500, "error": "Internal Server Error", "path": "/hotel/booking/2/transaction" }
0赞 Andrei Lisa 9/8/2023
您还能从应用程序中添加堆栈跟踪吗?
0赞 Andrei Lisa 9/8/2023
还有女巫版的Spring Boot,你用的吗?
0赞 munmun swami 9/8/2023
我已经添加了 ,但堆栈跟踪没有打印ex.printStackTrace()handleInvalidPaymentRequest

答:

0赞 lane.maxwell 9/8/2023 #1

这是因为你的 try/catch 块,永远不会从你的方法中被抛弃。InvalidPaymentModeException

实际上,你有这个:

try {
  throw new InvalidPaymentModeException();
} catch (Exception e) {
  com.example.bookingservice.dto.ErrorResponse errorResponseForOtherExceptions = new com.example.bookingservice.dto.ErrorResponse("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR.value());
  return new ResponseEntity(errorResponseForOtherExceptions,HttpStatus.INTERNAL_SERVER_ERROR);
}

因此,您抛出的异常正在被捕获,并且永远不会从此方法中抛出。这就是为什么你的建议没有被激发,相反,你得到了return new ResponseEntity(errorResponseForOtherExceptions,HttpStatus.INTERNAL_SERVER_ERROR);