Programmers Picnic • 0 to Infinity

Make an Ecommerce App using Spring Boot

Learn a complete ecommerce system using Spring Boot, MySQL, Thymeleaf, template inheritance, page-based transactions and API-based transactions. This lesson starts from zero and gradually moves toward production thinking.

Start with checkpoints Open library links

Spring Boot Ecommerce App SEO Image

What We Are Building

We are building an ecommerce app with product listing, product details, cart, checkout, order creation, stock reduction, admin product management, REST APIs, and reusable Thymeleaf layout files.

Page Flow

User opens pages like /products, /cart, and /checkout.

API Flow

JavaScript, mobile apps, or other clients call APIs like /api/products and /api/orders/checkout.

Transaction Flow

Important writes happen inside service methods using @Transactional.

Important Libraries and Official Links

Use standard and well-known Spring Boot libraries. These links are included so the student knows where to verify real documentation.

Maven Dependencies

Select these in Spring Initializr: Spring Web, Thymeleaf, Spring Data JPA, MySQL Driver, Validation, DevTools.

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
  </dependency>
</dependencies>

Architecture

Layer Purpose Example
Controller Returns Thymeleaf pages. ProductController
API Controller Returns JSON responses. ProductApiController
Service Business logic and transactions. OrderService
Repository Database access. ProductRepository
Entity Database table mapping. Product, CartItem, Order
Templates HTML pages and fragments. base.html, header.html, products/list.html

Thymeleaf Template Inheritance

Keep one base layout and insert changing page content into it. Header, footer, SEO blocks, script tags, and CSS links stay reusable.

templates/
  layout/base.html
  fragments/header.html
  fragments/footer.html
  products/list.html
  cart/view.html
  checkout/form.html
  admin/products/form.html

Transactions: Page and API Both

The page controller and API controller should both call the same service method. This prevents duplicate business logic.

@Service
public class OrderService {
  @Transactional
  public Order placeOrder(CheckoutRequest request) {
    // 1. Validate cart
    // 2. Create order
    // 3. Create order items
    // 4. Reduce product stock
    // 5. Clear cart
    // If anything fails, the whole transaction rolls back.
  }
}
Golden rule: Do not put transaction logic directly inside controllers. Put it in the service layer.

Checkpoint System

After every important step, check the URL, output, database, and browser console.

Checkpoint 1: Project Starts

Run:

mvn spring-boot:run

Open:

http://localhost:8080

You should see: the app responds. If no home page exists yet, a Whitelabel Error Page is acceptable at this stage.

Checkpoint 2: Home Page Works

Create: HomeController and home.html.

Open:

http://localhost:8080/

You should see: ecommerce home page with header, hero, and footer.

Checkpoint 3: Template Inheritance Works

Create: base.html, header.html, footer.html, home.html.

Open:

http://localhost:8080/

You should see: header and footer loaded from fragments, with home content inside the base layout.

Checkpoint 4: MySQL Connection Works

CREATE DATABASE ecommerce_db;
spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce_db
spring.datasource.username=root
spring.datasource.password=your_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Restart: mvn spring-boot:run

You should see: no database connection error.

Checkpoint 5: Product Table Created

Create: Product entity.

SHOW TABLES;

You should see: a product/products table in MySQL.

Checkpoint 6: Product Page Works

Open:

http://localhost:8080/products

You should see: product cards with name, price, stock, image, and Add to Cart button.

Checkpoint 7: Product API Works

Open:

http://localhost:8080/api/products

You should see JSON:

[
  {"id":1,"name":"Laptop","price":55000.0,"stock":10}
]

Checkpoint 8: Add to Cart from Page Works

Click: Add to Cart on a product.

Open:

http://localhost:8080/cart

You should see: the chosen product in cart with quantity and total price.

Checkpoint 9: Add to Cart from API Works

fetch("/api/cart/add", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ productId: 1, quantity: 2 })
})
.then(res => res.json())
.then(console.log);

You should see: success: true. Then open /cart and see the item.

Checkpoint 10: Checkout Page Transaction Works

Open:

http://localhost:8080/checkout

You should see: order confirmation, order ID, reduced stock, and empty cart after success.

Checkpoint 11: Checkout API Transaction Works

fetch("/api/orders/checkout", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    customerName: "Test User",
    address: "Test Address",
    paymentMode: "COD"
  })
})
.then(res => res.json())
.then(console.log);

You should see: order ID in JSON, order saved in MySQL, stock reduced, and cart cleared.

Checkpoint 12: JS Files Load

Open DevTools → Network → JS.

You should see status 200 for: app.js, cart.js, api-demo.js, speak.js.

Files Included in this ZIP

Final Master Check

Page Flow and API Flow Both Work

Open page URLs:

http://localhost:8080/
http://localhost:8080/products
http://localhost:8080/cart
http://localhost:8080/checkout
http://localhost:8080/admin/products

Open API URLs:

http://localhost:8080/api/products
http://localhost:8080/api/cart
http://localhost:8080/api/orders

You should prove:

  • Products on pages match products from API.
  • Cart changes from page appear in API.
  • Cart changes from API appear on page.
  • Checkout from page creates an order in MySQL.
  • Checkout from API creates an order in MySQL.
  • Stock reduction, cart clearing, and order creation happen together as one transaction.

Speak Tag Requirement Used in This Page

This page uses numbered speak tags exactly as required by the speaking system: speak0, speak1, speak2, and so on. The speaking JavaScript reads elements whose IDs start with speak and match the numeric pattern.

Check Speak Tags

Open DevTools Console and run:

[...document.querySelectorAll('[id^="speak"]')].map(x => x.id)

You should see: speak0, speak1, speak2, speak3, and more numbered speak sections.