Workbook 8.1
A resilient API will send back a 4xx status code when it receives a bad request.
Launch the starter project
The Problem
If the consumer sends a bad request (passes an id that doesn't exist), the application fails and throws an unchecked exception during the runtime.
It responds with a status code of 500.
The 500 status code should be reserved for actual server failures due to unexpected scenarios, like high resource usage (CPU / Physical Memory), database-related failure, etc...
If a consumer sends an id
that doesn't exist, such a scenario should be expected. The developer must anticipate this scenario and ensure that the application does not fail. It must be fully equipped to handle the bad request and respond with a 4xx status code.
Task 1
Create a new folder called exception
. Inside the folder, create a NoContactException
class.
Use the following code to create a custom checked exception:
public class NoContactException extends Exception {
}
If you took our Java course, a checked exception forces you to:
try
to run a piece of code.catch
the exception if it fails.
Task 2
Modify the findIndexById
function to throw the NoContactException
.
private int findIndexById(String id) throws NoContactException {
return IntStream.range(0, contactRepository.getContacts().size())
.filter(index -> contactRepository.getContacts().get(index).getId().equals(id))
.findFirst()
.orElseThrow(() -> new NoContactException());
}
Task 3
Every Service
function that calls findIndexById()
is at risk of throwing a NoContactException
.
Modify the interface methods inside ContactService
.
Contact getContactById(String id) throws NoContactException;
void saveContact(Contact contact);
void updateContact(String id, Contact contact) throws NoContactException;
void deleteContact(String id) throws NoContactException;
List<Contact> getContacts();
Fix the errors inside ContactServiceImpl
.
@Override
public Contact getContactById(String id) throws NoContactException {
return contactRepository.getContact(findIndexById(id));
}
// etc...
Task 4
Inside the handler method: getContact
, try
to run the current code.
try { Contact contact = contactService.getContactById(id); return new ResponseEntity<>(contact, HttpStatus.OK); }
catch
the exception in the event of a failure.
catch (NoContactException e)
If there is a failure, which status code should we return?
return new ResponseEntity<>(CHOOSE_STATUS_CODE);
Choose the most appropriate status code from Mozilla Status Codes.
Task 5
In similar fashion, handle the exceptions inside updateContact
and deleteContact
.
Task 6
Test your API using Postman. First create the following resources:
{ "name": "Jon Snow", "phoneNumber": "6129439432" } { "name": "The Hound", "phoneNumber": "4125429422" } { "name": "Tyrion Lannister", "phoneNumber": "4515429321" }
Test Case 1
-
GET: localhost:8080/contact/all
-
Status Code: 200
[ { "id": "392963d8-cd35-4b6a-a881-c759b744029a", "name": "Jon Snow", "phoneNumber": "6129439432" }, { "id": "1e8c9503-3ce9-4d7a-b0f0-af4c25e6ecbd", "name": "The Hound", "phoneNumber": "4125429422" }, { "id": "e8820ff1-d0cb-49fe-9bf3-8f0a4549fdb3", "name": "Tyrion Lannister", "phoneNumber": "4515429321" } ]
Test Case 2
-
GET: localhost:8080/contact/123
-
Status Code:
404 Not Found
Test Case 3
PUT: localhost:8080/contact/123
- Status Code:
400 Bad Request
Test Case 4
PUT: localhost:8080/contact/123
Request Body { "name": "Tyrion Lannister", "phoneNumber": "4515429321" }
- Status Code:
404 Not Found
Test Case 5
DELETE: localhost:8080/contact/123
- Status Code:
404 Not Found