An e-commerce web application for home decoration products, built with Spring Boot and Thymeleaf.
- Prerequisites
- Installation Guide
- Project Structure
- Features
- Database Schema
- API Endpoints
- Troubleshooting
- Tech Stack
| Component | Version | Note |
|---|---|---|
| Java JDK | 20 | Required. Download from https://jdk.java.net/ |
| MySQL | 8.x | Required. Download from https://dev.mysql.com/ |
| Maven | 3.6+ | Optional (Maven Wrapper is included) |
| IDE | IntelliJ / VSCode | IntelliJ IDEA recommended |
Download and install MySQL Community Server 8.x.
During installation, take note of:
- Username: default is
root - Password: the password you set during installation
- Port: default is
3306
Verify MySQL is running:
mysql -u root -pEnter your password. If you see the MySQL shell prompt, the installation was successful.
Open the MySQL shell or MySQL Workbench and run:
CREATE DATABASE unidecor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Note: You do NOT need to create tables manually. Spring Boot (Hibernate) will auto-create all tables on the first run.
The application.properties file is gitignored and not included in the repository. You must create it manually.
Create the file at:
src/main/resources/application.properties
Copy the following content and update with your own values:
# =============================================
# DATABASE
# =============================================
spring.datasource.url=jdbc:mysql://localhost:3306/unidecor?useSSL=false&serverTimezone=Asia/Ho_Chi_Minh&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=YOUR_MYSQL_PASSWORD
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# =============================================
# JPA / HIBERNATE
# =============================================
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.format_sql=true
# =============================================
# THYMELEAF
# =============================================
spring.thymeleaf.cache=false
# =============================================
# SERVER
# =============================================
server.port=8080
# =============================================
# GOOGLE OAUTH2 (optional - see Step 4)
# =============================================
spring.security.oauth2.client.registration.google.client-id=YOUR_GOOGLE_CLIENT_ID
spring.security.oauth2.client.registration.google.client-secret=YOUR_GOOGLE_CLIENT_SECRET
# =============================================
# EMAIL (optional - see Step 5)
# =============================================
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=YOUR_EMAIL@gmail.com
spring.mail.password=YOUR_APP_PASSWORD
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=trueReplace the placeholder values:
YOUR_MYSQL_PASSWORD— your MySQL root passwordYOUR_GOOGLE_CLIENT_ID/YOUR_GOOGLE_CLIENT_SECRET— Google OAuth credentials (see Step 4)YOUR_EMAIL@gmail.com/YOUR_APP_PASSWORD— Gmail and app password (see Step 5)
If you want to enable "Sign in with Google":
- Go to https://console.cloud.google.com/
- Create a new project (or select an existing one)
- Navigate to APIs & Services > Credentials
- Click Create Credentials > OAuth Client ID
- Select Application type: Web application
- Add Authorized redirect URIs:
http://localhost:8080/login/oauth2/code/google - Copy the Client ID and Client Secret into your
application.properties
If you don't need Google login, the app will still work with email/password authentication. However, you may need to comment out the oauth2Login section in SecurityConfig.java to avoid startup errors.
If you want to enable email features (order confirmation, etc.):
- Log in to your Google Account at https://myaccount.google.com/
- Go to Security > 2-Step Verification (enable it if not already enabled)
- Go to App passwords > Generate a new app password
- Copy the 16-character app password into
spring.mail.passwordin yourapplication.properties
If you don't need email functionality, you can skip this step.
Open a terminal in the project root directory and run:
Windows (CMD or PowerShell):
mvnw.cmd spring-boot:runWindows (Git Bash):
./mvnw spring-boot:runIf Maven is installed globally:
mvn spring-boot:runWait until you see this log message:
Started DecorApplication in X.XXX seconds
The project is now running successfully.
Open your browser and navigate to:
| Page | URL |
|---|---|
| Homepage | http://localhost:8080/ |
| Login | http://localhost:8080/user/login |
| Register | http://localhost:8080/user/register |
| Admin Dashboard | http://localhost:8080/admin |
Note: The Admin Dashboard requires an account with the admin role.
UniDecor/
├── src/
│ ├── main/
│ │ ├── java/uni/decor/
│ │ │ ├── DecorApplication.java # Main entry point
│ │ │ ├── common/ # Enums, shared logger
│ │ │ ├── config/ # Security, Thymeleaf, VNPay config
│ │ │ ├── controller/ # MVC Controllers
│ │ │ │ ├── HomeController.java # Homepage + Admin dashboard
│ │ │ │ ├── ProductController.java # Product browsing & search
│ │ │ │ ├── CartController.java # Shopping cart
│ │ │ │ ├── OrderController.java # Order placement
│ │ │ │ ├── PaymentController.java # Payment (VNPay, MoMo)
│ │ │ │ ├── UserController.java # Login, register, account
│ │ │ │ ├── BlogController.java # Blog pages
│ │ │ │ ├── CollectionController.java # Category collections
│ │ │ │ ├── ManageBlogController.java # Admin - Blog management
│ │ │ │ ├── ManageCategoryController.java # Admin - Category management
│ │ │ │ ├── ManageOrderController.java # Admin - Order management
│ │ │ │ ├── ManageProductController.java # Admin - Product management
│ │ │ │ └── ManageVoucherController.java # Admin - Voucher management
│ │ │ ├── dto/ # Data Transfer Objects
│ │ │ ├── encryption/ # Encryption utilities
│ │ │ ├── entity/ # JPA Entities
│ │ │ │ ├── User.java
│ │ │ │ ├── Product.java
│ │ │ │ ├── ProductVariant.java
│ │ │ │ ├── Category.java
│ │ │ │ ├── Order.java
│ │ │ │ ├── OrderVariant.java
│ │ │ │ ├── OrderState.java
│ │ │ │ ├── CartItem.java
│ │ │ │ ├── Blog.java
│ │ │ │ ├── Review.java
│ │ │ │ ├── Role.java
│ │ │ │ ├── Voucher.java
│ │ │ │ └── VoucherUsage.java
│ │ │ ├── repository/ # Spring Data JPA Repositories
│ │ │ ├── rest/ # REST API (search, image upload)
│ │ │ ├── service/ # Business logic layer
│ │ │ └── util/ # Utility classes
│ │ └── resources/
│ │ ├── application.properties # (must be created manually - gitignored)
│ │ ├── static/ # CSS, JS, assets
│ │ └── templates/ # Thymeleaf HTML templates
│ │ ├── index.html # Homepage
│ │ ├── product.html # Product detail
│ │ ├── cart.html # Shopping cart
│ │ ├── admin/ # Admin interface
│ │ ├── user/ # Login, register, account
│ │ ├── order/ # Order pages
│ │ ├── blog/ # Blog pages
│ │ ├── category/ # Category pages
│ │ ├── pay/ # Payment pages
│ │ └── layout/ # Shared layout templates
│ └── test/ # Unit tests
├── pom.xml # Maven dependencies
├── mvnw / mvnw.cmd # Maven Wrapper
└── .gitignore
- Browse products by category
- Search products
- View product details with multiple variants (color, size)
- Add products to shopping cart
- Place orders with receiver information
- Pay via VNPay (sandbox) or MoMo
- Apply voucher discount codes
- Register with email/password or Google OAuth2
- Login / Logout
- View account information
- Track orders
- Read blog posts
- Dashboard with statistics (payment methods, best-selling products)
- Manage products (CRUD) with product variants
- Manage categories
- Manage orders
- Manage blog posts (CRUD)
- Manage voucher discount codes
All tables are auto-created by Hibernate on first run:
| Table | Description |
|---|---|
| users | User accounts |
| roles | Roles (admin, user) |
| user_roles | User-role mapping (Many-to-Many) |
| products | Products |
| product_variants | Product variants (color, size, price) |
| categories | Product categories |
| orders | Customer orders |
| order_variants | Order line items (products in an order) |
| order_states | Order status history |
| cart_items | Shopping cart items |
| reviews | Product reviews |
| blogs | Blog posts |
| vouchers | Discount voucher codes |
| voucher_usages | Voucher usage history |
| Method | URL | Description |
|---|---|---|
| GET | / | Homepage |
| GET | /product/{slug} | Product detail |
| GET | /product/search | Search products |
| GET | /cart | View cart |
| POST | /cart/add | Add item to cart |
| GET | /order | Checkout page |
| POST | /order | Submit order |
| GET | /order/search | Track order |
| GET | /pay/vnpay | VNPay payment |
| GET | /user/login | Login page |
| GET | /user/register | Register page |
| GET | /user/account | Account info |
| GET | /blog | Blog listing |
| GET | /collections | Category listing |
| Method | URL | Description |
|---|---|---|
| GET | /admin | Dashboard |
| GET | /admin/product/list | Product list |
| GET | /admin/product/add | Add product |
| GET | /admin/product/edit/{id} | Edit product |
| GET | /admin/category/list | Category list |
| GET | /admin/order/list | Order list |
| GET | /admin/blog/list | Blog list |
| GET | /admin/voucher/list | Voucher list |
| Method | URL | Description |
|---|---|---|
| GET | /api/search | Search products (AJAX) |
| POST | /api/upload | Upload image |
Cause: The application.properties file is gitignored and not included in the repository.
Fix: Create the file at src/main/resources/application.properties following Step 3 above.
Cause: Wrong MySQL password.
Fix: Double-check spring.datasource.password in your application.properties.
Cause: MySQL is not running or the port is wrong.
Fix:
- Check that MySQL is running (Windows Services > MySQL80)
- Verify the port in
spring.datasource.urlmatches your MySQL port (default is 3306)
Cause: The database has not been created yet.
Fix: Run CREATE DATABASE unidecor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; in MySQL.
Cause: Missing Google OAuth2 configuration.
Fix: Add Google OAuth credentials to application.properties (see Step 4), or if you don't need OAuth, comment out the oauth2Login section in SecurityConfig.java.
Cause: Another application is using port 8080.
Fix: Change the port in application.properties:
server.port=9090Then access the app at http://localhost:9090/
| Component | Technology |
|---|---|
| Backend Framework | Spring Boot 3.0.6 |
| Java Version | 20 |
| Template Engine | Thymeleaf |
| Database | MySQL 8.x |
| ORM | Spring Data JPA / Hibernate |
| Security | Spring Security 6 + OAuth2 |
| Payment | VNPay (sandbox), MoMo |
| Build Tool | Maven |
| Utilities | Lombok, MapStruct |
| Spring Boot Mail (Gmail SMTP) |