Reputation: 23
I´m beginner in REST API and Spring Boot. I have a doubt about how to handle the different responses a request can have. For example if I post data of a credit card
{
"number": "3434 3434 3434 3434",
"date_expiration": "09-19",
"identification_card": 23232323
}
then in @RestController
@PostMapping("/card")
public ResponseEntity<CreditCard> payCard(@Valid @RequestBody CreditCard creditCard){
CreditCard creC = cardService.registerCard(creditCard);
return new ResponseEntity<>(creC, HttpStatus.OK);
}
In this case I return an object of ResponseEntity.
What happens if the date_expiration
is expired or the identification_card
doesn't correspond to the client? They are logical validations that are resolved in the service and can trigger different responses. How should I handle them?
Upvotes: 0
Views: 2680
Reputation: 3390
Well, if date_expiration
is expired or identification_card
doesn't behave to the customer, this is a business failure.
I like to represent Business Errors with an HTTP 422 - Unprocessable Entity
. See here
You can change the return object from ResponseEntity<CreditCard>
to ResponseEntity<Object>
if you want to return diferent objects in your controller, although I prefer to use a ExceptionHandler
in a ControllerAdvice
annotated method if the purpose is to return errors.
As I said, this situation is a business failure (the credit card is expired or doesn't behave to the current user).
Here's an example. Would be something like this:
CardService.java
@Service
public class CardService {
// ..
public CreditCard registerCard(CreditCard card) throws BusinessException {
if(cardDoesntBehaveToUser(card, currentUser()))) // you have to get the current user
throw new BusinessException("This card doesn't behave to the current user");
if(isExpired(card)) // you have to do this logic. this is just an example
throw new BusinessException("The card is expired");
return cardRepository.save(card);
}
}
CardController.java
@PostMapping("/card")
public ResponseEntity<Object> payCard(@Valid@RequestBody CreditCard creditCard) throws BusinessException {
CreditCard creC = cardService.registerCard(creditCard);
return ResponseEntity.ok(creC);
}
BusinessException.java
public class BusinessException extends Exception {
private BusinessError error;
public BusinessError(String reason) {
this.error = new BusinessError(reason, new Date());
}
// getters and setters..
}
BusinessError.java
public class BusinessError {
private Date timestamp
private String reason;
public BusinessError(String Reason, Date timestamp) {
this.timestamp = timestamp;
this.reason = reason;
}
// getters and setters..
}
MyExceptionHandler.java
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {
// .. other handlers..
@ExceptionHandler({ BusinessException.class })
public ResponseEntity<Object> handleBusinessException(BusinessException ex) {
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(ex.getError());
}
}
If the credit card is expired, the JSON will be rendered as:
{
"timestamp": "2019-10-29T00:00:00+00:00",
"reason": "The card is expired"
}
Upvotes: 0
Reputation: 4483
Here you are using same object as your Request body and Response body. That is not a standard practice.
You should have separate objects for Request/Response. In request object you should have only the information you need from the user. But in the response object you should have information you want to send in response and also validation information like Error Details which includes error code and error description which you can use to display validation error to the user.
Hope this helps.
Upvotes: 1