Skip to content

omariomari2/Go-Shop

Repository files navigation

GoShop Backend - Spring Boot

A Spring Boot backend implementation for the GoShop e-commerce platform, using MongoDB for data persistence and JWT-based authentication.

Features

  • Authentication: User signup, signin, signout with JWT cookies
  • Product Management: Browse products by market, with automatic data seeding
  • Shopping Cart: Anonymous and authenticated cart management with merge functionality
  • Security: Spring Security with JWT, BCrypt password hashing
  • Database: MongoDB with Spring Data MongoDB
  • Static File Serving: Serves frontend files directly

Technology Stack

  • Java: 17+
  • Framework: Spring Boot 3.2.0
  • Database: MongoDB
  • Security: Spring Security + JWT
  • Build Tool: Gradle

Prerequisites

  • Java 17 or higher
  • MongoDB (local or MongoDB Atlas)
  • Gradle (included via wrapper)

Getting Started

1. Install MongoDB

On Ubuntu/Debian:

sudo apt-get install mongodb
sudo systemctl start mongodb

Using Docker:

docker run -d -p 27017:27017 --name mongodb mongo:latest

Using MongoDB Atlas: Sign up at https://www.mongodb.com/cloud/atlas and get your connection URI.

2. Configure Environment Variables

Create a .env file in the backend directory or set environment variables:

export MONGODB_URI=mongodb://localhost:27017/goshop
export JWT_SECRET=your-very-long-secret-key-at-least-32-characters-for-production
export PORT=8080

3. Run the Application

Development mode:

cd backend
./gradlew bootRun

With specific profile:

./gradlew bootRun --args='--spring.profiles.active=dev'

Build and run JAR:

./gradlew build
java -jar build/libs/goshop-backend-0.0.1-SNAPSHOT.jar

4. Access the Application

API Endpoints

Authentication

Endpoint Method Description
/api/auth/signup POST Create new user account
/api/auth/signin POST Sign in to existing account
/api/auth/signout POST Sign out and clear session
/api/auth/me GET Get current user info

Products

Endpoint Method Description
/api/products GET Get all products (optional ?market=slug filter)
/api/products/:id GET Get single product

Cart

Endpoint Method Description
/api/cart GET Get current cart
/api/cart/count GET Get cart item count
/api/cart/items POST Add item to cart
/api/cart/items/:id PATCH Update cart item quantity
/api/cart/items/:id DELETE Remove item from cart
/api/cart/merge POST Merge anonymous cart with user cart

Health

Endpoint Method Description
/health GET Health check endpoint

Project Structure

backend/
├── src/
│   ├── main/
│   │   ├── java/com/goshop/
│   │   │   ├── GoShopApplication.java          # Main application class
│   │   │   ├── config/                          # Configuration classes
│   │   │   │   ├── SecurityConfig.java          # Spring Security config
│   │   │   │   ├── MongoConfig.java             # MongoDB config
│   │   │   │   └── WebConfig.java               # Web/CORS config
│   │   │   ├── controller/                      # REST controllers
│   │   │   │   ├── AuthController.java
│   │   │   │   ├── ProductController.java
│   │   │   │   ├── CartController.java
│   │   │   │   └── HealthController.java
│   │   │   ├── service/                         # Business logic
│   │   │   │   ├── AuthService.java
│   │   │   │   ├── ProductService.java
│   │   │   │   └── CartService.java
│   │   │   ├── repository/                      # MongoDB repositories
│   │   │   │   ├── UserRepository.java
│   │   │   │   ├── ProductRepository.java
│   │   │   │   └── CartRepository.java
│   │   │   ├── model/                           # MongoDB documents
│   │   │   │   ├── User.java
│   │   │   │   ├── Product.java
│   │   │   │   ├── Cart.java
│   │   │   │   └── CartItem.java
│   │   │   ├── dto/                             # Data Transfer Objects
│   │   │   │   ├── SignupRequest.java
│   │   │   │   ├── SigninRequest.java
│   │   │   │   ├── AddToCartRequest.java
│   │   │   │   ├── UpdateCartItemRequest.java
│   │   │   │   ├── UserResponse.java
│   │   │   │   ├── CartResponse.java
│   │   │   │   └── ErrorResponse.java
│   │   │   ├── security/                        # JWT security
│   │   │   │   ├── JwtTokenProvider.java
│   │   │   │   └── JwtAuthenticationFilter.java
│   │   │   └── exception/                       # Exception handling
│   │   │       ├── GlobalExceptionHandler.java
│   │   │       └── [custom exceptions]
│   │   └── resources/
│   │       ├── application.yml                  # Main config
│   │       ├── application-dev.yml              # Dev config
│   │       └── application-prod.yml             # Production config
│   └── test/
├── build.gradle                                 # Gradle build config
├── settings.gradle                              # Gradle settings
└── gradlew                                      # Gradle wrapper

Data Seeding

The application automatically seeds the database with 9 products across 3 markets on first startup:

  • Kaneshie Market: Fresh Bananas, Fresh Herbs, Fresh Tomatoes
  • Accra Market: Roma Tomatoes, Imported Rice, Green Apples
  • Kumasi Market: Garden Eggs, Kontomire Leaves, Local Red Rice

Configuration

application.yml

Main configuration file with sensible defaults:

spring:
  data:
    mongodb:
      uri: ${MONGODB_URI:mongodb://localhost:27017/goshop}
  security:
    jwt:
      secret: ${JWT_SECRET}
      expiration: 604800000  # 7 days

server:
  port: ${PORT:8080}

Environment Variables

Variable Description Default
MONGODB_URI MongoDB connection string mongodb://localhost:27017/goshop
JWT_SECRET Secret key for JWT signing Must be set in production
PORT Server port 8080

Authentication

The backend uses JWT tokens stored in HTTP-only cookies:

  • Cookie Name: SESSION
  • Expiration: 7 days
  • Flags: httpOnly, sameSite=Lax

Password Security

  • Passwords are hashed using BCrypt with strength 10
  • Original passwords are never stored

Cart Management

Anonymous Carts

  • Created automatically on first add-to-cart
  • Tracked via CART_ID cookie
  • 30-day expiration

Authenticated Carts

  • Tied to user ID
  • Anonymous cart can be merged on login

Development

Running Tests

./gradlew test

Building for Production

./gradlew clean build

The JAR file will be created in build/libs/.

Hot Reload

Use Spring Boot DevTools for automatic restart on code changes:

./gradlew bootRun

Migration from Node.js

This backend is a drop-in replacement for the Node.js backend:

  1. No Frontend Changes: All API endpoints maintain the same contract
  2. Cookie Compatibility: Uses same cookie names (SESSION, CART_ID)
  3. Response Format: Maintains identical JSON structure
  4. Status Codes: Returns same HTTP status codes

Troubleshooting

MongoDB Connection Issues

# Check if MongoDB is running
sudo systemctl status mongodb

# Start MongoDB
sudo systemctl start mongodb

# Check connection
mongo --eval "db.adminCommand('ping')"

Port Already in Use

# Find process using port 8080
lsof -i :8080

# Kill the process
kill -9 <PID>

# Or use different port
export PORT=8081
./gradlew bootRun

JWT Secret Too Short

Ensure your JWT_SECRET is at least 32 characters long:

export JWT_SECRET="your-very-long-secret-key-minimum-32-characters-required-for-hmac-sha256"

Production Deployment

  1. Set Environment Variables:

    export SPRING_PROFILES_ACTIVE=prod
    export MONGODB_URI=your-production-mongodb-uri
    export JWT_SECRET=your-secure-secret-key
    export PORT=8080
  2. Build the Application:

    ./gradlew clean build
  3. Run the JAR:

    java -jar build/libs/goshop-backend-0.0.1-SNAPSHOT.jar
  4. Or use Docker:

    FROM openjdk:17-slim
    COPY build/libs/goshop-backend-0.0.1-SNAPSHOT.jar app.jar
    ENTRYPOINT ["java", "-jar", "/app.jar"]

License

MIT