To read one product, a client puts its id in the path: /products/3. A mapping written as /products/{productId} catches that piece of the path, and a parameter @PathVariable int productId hands it to your method as a whole number.
This time the database does the searching, with a WHERE condition. You never paste the value into the SQL text: you write a placeholder, ?, and pass the value separately, after the SQL. db.queryForList gives the matching rows, or an empty list when the query found nothing. For example, with a table books:
List<Map<String, Object>> books = db.queryForList("SELECT * FROM books WHERE year = ?", 1965);
if (books.isEmpty()) {
System.out.println("No book from 1965");
}
When no row matches, the client asked for something that doesn't exist, so the answer is 404 with an error message: ResponseEntity.status(404).body(...) sets the status. A method that answers either a map or a ResponseEntity returns Object, and Java checks that every path through it returns something.
GET /products/3 → 200 {"id": 3, "name": "Lamp", "price": 29, "category": "home", "stock": 1}
GET /products/8 → 200 {"id": 8, "name": "Gift card", "price": 50, "category": null, "stock": 999}
GET /products/99 → 404 {"error": "Product not found"}
GET /products/0 → 404 {"error": "Product not found"}
Your task: add GET /products/{productId}, whose method asks the database for that product with a placeholder and answers it as JSON, or {"error": "Product not found"} with the status 404.
Assignment
Follow the Coding Tutorial to add the mapping and its method getProduct.
HintqueryForList gives an empty list when the query finds nothing. Check rows.isEmpty() before you return the first row, rows.get(0).
Free plan: 30 tutor messages. PRO is unlimited.
