Start learning free

LESSON 33 OF 173 · BACKEND: YOUR FIRST API

Reviews for a Product in Java

Practice

Customers can now review a product: a number of stars from 1 to 5 and a short text. A review belongs to one product, so its path goes under the product's path: /products/1/reviews are the reviews of product 1. This is a nested path, and the id in the middle is a path variable, {productId}, as in GET /products/1.

The reviews are already in the file, in the map reviews: each key is a product id, and each value is the list of that product's reviews. A product with no reviews has no key, so reviews.get gives null for it, and calling add on null crashes. getOrDefault reads a list safely, and putIfAbsent stores an empty list only when the key is missing. The same map of lists, with other values:

Map<Integer, List<String>> tags = new HashMap<>();
tags.put(1, new ArrayList<>(List.of("sale", "new")));
System.out.println(tags.getOrDefault(1, List.of()));   // [sale, new]
System.out.println(tags.getOrDefault(2, List.of()));   // []
tags.putIfAbsent(2, new ArrayList<>());
tags.get(2).add("gift");
System.out.println(tags.get(2));   // [gift]

One path can have a route for each method: GET reads a product's reviews, and POST adds one and answers 201 with it. Both answer 404 when no product has the id. The GET route, getReviews, is already in your file. Your code must answer these requests, in this order:

GET /products/1/reviews  →  200  [{"stars": 5, "text": "Great mug"}, {"stars": 4, "text": "A bit small"}]
GET /products/4/reviews  →  200  []
GET /products/99/reviews  →  404  {"error": "Product not found"}
POST /products/2/reviews  {"stars": 4, "text": "Nice paper"}  →  201  {"stars": 4, "text": "Nice paper"}
GET /products/2/reviews  →  200  [{"stars": 4, "text": "Nice paper"}]
POST /products/1/reviews  {"stars": 3, "text": "The handle gets hot"}  →  201  {"stars": 3, "text": "The handle gets hot"}
GET /products/1/reviews  →  200  [{"stars": 5, …}, {"stars": 4, …}, {"stars": 3, "text": "The handle gets hot"}]
POST /products/99/reviews  {"stars": 5, "text": "Love it"}  →  404  {"error": "Product not found"}
GET /products/1  →  200  {"id": 1, "name": "Mug", "price": 12, "category": "kitchen"}

Your task: below getReviews, add a POST route for /products/{productId}/reviews. It adds the review at the end of the product's list, giving the product an empty list first when it has none, and answers 201 with the review; it answers 404 when the product doesn't exist.


Assignment
Follow the Coding Tutorial to build addReview on the nested path, next to getReviews.


Hint
Find the product first, with the loop and if of getReviews. reviews.putIfAbsent(productId, new ArrayList<>()) makes sure the product has a list; then reviews.get(productId) is that list, and add puts the review at its end.


STEP 1 OF 8
    Ctrl + Enter to check

    Shop Reviews in Java

    Keep going with Java1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free