Real World Example

A Catalogue API Like Flipkart's Home Page

The first screen of any shopping app calls a catalogue API to list products by category. Here is the ShopEase version for this level: an in-memory list, a service and a controller. In the medium level you will add full CRUD, and later a real database.

package com.shopease.product;

import java.math.BigDecimal;
import java.util.List;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    private final List<Product> products = List.of(
        new Product(1L, "Boat Rockerz 450", "Wireless headphones", new BigDecimal("1499.00"), 25, "Electronics"),
        new Product(2L, "Clean Code", "Book by Robert C. Martin", new BigDecimal("599.00"), 40, "Books"),
        new Product(3L, "Cotton T-Shirt", "Regular fit, navy blue", new BigDecimal("399.00"), 0, "Fashion"),
        new Product(4L, "Redmi Note 13", "6 GB RAM, 128 GB", new BigDecimal("16999.00"), 12, "Electronics"));

    public List<Product> findAll() {
        return products;
    }

    public List<String> categories() {
        return products.stream().map(Product::category).distinct().sorted().toList();
    }
}
package com.shopease.product;

import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/products")
public class ProductController {
    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping
    public List<Product> all() {
        return productService.findAll();
    }

    @GetMapping("/categories")
    public List<String> categories() {
        return productService.categories();
    }
}

Try It

Example

curl -s http://localhost:8080/api/products/categories
curl -s http://localhost:8080/api/products

Example output

["Books","Electronics","Fashion"]
[{"id":1,"name":"Boat Rockerz 450","description":"Wireless headphones","price":1499.00,"stock":25,"category":"Electronics"},{"id":2,"name":"Clean Code","description":"Book by Robert C. Martin","price":599.00,"stock":40,"category":"Books"},{"id":3,"name":"Cotton T-Shirt","description":"Regular fit, navy blue","price":399.00,"stock":0,"category":"Fashion"},{"id":4,"name":"Redmi Note 13","description":"6 GB RAM, 128 GB","price":16999.00,"stock":12,"category":"Electronics"}]

The Service Logic, Runnable

Example

The service code is plain Java, so you can run (and unit test) it without starting Spring:

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        ProductService service = new ProductService();
        System.out.println("Categories: " + service.categories());
        System.out.println("Count per category: " + service.countByCategory());
        System.out.println("Cheapest in stock: " + service.cheapestInStock().name());
    }
}

record Product(Long id, String name, String description, BigDecimal price, int stock, String category) {}

class ProductService {
    private final List<Product> products = List.of(
        new Product(1L, "Boat Rockerz 450", "Wireless headphones", new BigDecimal("1499.00"), 25, "Electronics"),
        new Product(2L, "Clean Code", "Book by Robert C. Martin", new BigDecimal("599.00"), 40, "Books"),
        new Product(3L, "Cotton T-Shirt", "Regular fit, navy blue", new BigDecimal("399.00"), 0, "Fashion"),
        new Product(4L, "Redmi Note 13", "6 GB RAM, 128 GB", new BigDecimal("16999.00"), 12, "Electronics"));

    List<String> categories() {
        return products.stream().map(Product::category).distinct().sorted().toList();
    }

    Map<String, Long> countByCategory() {
        return products.stream().collect(Collectors.groupingBy(Product::category, TreeMap::new, Collectors.counting()));
    }

    Product cheapestInStock() {
        return products.stream().filter(p -> p.stock() > 0)
            .min((a, b) -> a.price().compareTo(b.price())).orElseThrow();
    }
}

Output

Categories: [Books, Electronics, Fashion]
Count per category: {Books=1, Electronics=2, Fashion=1}
Cheapest in stock: Clean Code

Practice

Exercise: Add GET /api/products/summary returning {"totalProducts":4,"inStock":3}.

Show answer
@GetMapping("/summary")
public Map<String, Long> summary() {
    List<Product> all = productService.findAll();
    long inStock = all.stream().filter(p -> p.stock() > 0).count();
    return Map.of("totalProducts", (long) all.size(), "inStock", inStock);
}