@JsonProperty(WRITE_ONLY) ensures that the password is accepted from the request but not
exposed in the response, improving security.
@Enumerated([Link]) is used to store enum values as strings in the database
instead of ordinal values, which improves readability and avoids issues if enum order changes.
@ElementCollection
@CollectionTable(name = "user_addresses", joinColumns = @JoinColumn(name = "user_id"))
private Set<Address> addresses = new HashSet<>();
It creates separate table automatically
@CollectionTable is used to define the table for storing element collections and specify the join
column mapping.
JsonIgnore → "Don't show in response"
Cascade → "Parent action → Child action"
Even though fields are stored in the same table, @Embedded is used to logically group related
fields, improve code readability, enable reusability, and make the code easier to maintain.
orphanRemoval = true automatically deletes child entities when they are removed from the
parent collection.
If a child entity is removed from the parent, it will be automatically deleted from the
database.
Example
@OneToMany(mappedBy = "user", orphanRemoval = true)
private List<Address> addresses;
Now imagine:
User has 2 addresses:
User
├── Address 1
└── Address 2
If you remove one address:
[Link]().remove(address1);
Because of:
orphanRemoval = true
👉 Address1 will be deleted from database automaticall
Without orphanRemoval
If you remove:
[Link]().remove(address1);
Address still remains in database ❌
(Just not linked to user)
This creates orphan records (unused data)
@Embeddable defines a reusable class. When used with @Embedded, fields are stored in same table. When used with
@ElementCollection, multiple values are stored in a separate collection table.
@Embeddable + @Embedded (Same Table)
@Embeddable
class Address {
String city;
}
@Entity
class User {
@Embedded
Address address;
}
👉 Stored in User table
@Embeddable + @ElementCollection (Separate Table)
@Embeddable
class Address {
String city;
}
@Entity
class User {
@ElementCollection
Set<Address> addresses;
}
👉 Stored in Separate table
By extending JpaRepository, you automatically get built-in methods like:
o save()
o findById()
o findAll()
o delete()
So you don't need to write basic database operations manually
Spring Data JPA automatically generates queries based on method names. derived query method
We use Repository to interact with the database. By extending JpaRepository, we get built-in CRUD operations and avoid
writing boilerplate code. Spring Data JPA automatically handles database interactions.
public interface ProductRepository extends JpaRepository<Product, Long>,
JpaSpecificationExecutor<Product> {
List<Product> findBySellerId(Long id);
@Query("""
SELECT p FROM Product p
WHERE (:query IS NULL
OR LOWER([Link]) LIKE LOWER(CONCAT('%', :query, '%'))
OR LOWER([Link]) LIKE LOWER(CONCAT('%', :query, '%'))
)
""")
List<Product> searchProduct(@Param("query") String query);
}
JpaSpecificationExecutor is used to create dynamic queries based on multiple conditions.
Enums are used to define fixed set of constants. USER_ROLE defines user roles and PaymentMethod defines available
payment methods, improving type safety and code readability.
package [Link];
public enum AccountStatus {
PENDING_VERIFICATION, //Account is created but not yet verified
ACTIVE, //Account is active and in good standing
SUSPENDED, //Account is temporarily suspended
DEACTIVATED, //Account is deactivated , user may have chosen to deactivate it
BANNED, //Account is permanently banned due to server violations
CLOSED //Account is permanently closed , possibly at user request
}
E-Commerce API Design (Interview-Ready)
Overview
I designed RESTful APIs by separating modules like Authentication, User, Seller, Cart, Product, Category,
Order, Payment, and Transaction. Each module has its own controller and endpoints. I used proper HTTP
methods (GET, POST, PUT, DELETE) and implemented JWT-based authentication with role-based access
control.
1. Auth APIs
POST /api/auth/signup
POST /api/auth/send/login-signup-otp
POST /api/auth/signing
Purpose:
Handles user signup and login using OTP. Generates JWT token after successful authentication.
2. User APIs
GET /api/user/profile
Purpose:
Fetch logged-in user profile using JWT token.
3. Seller APIs
POST /api/seller/login
POST /api/seller
PATCH /api/seller/verify/{email}/{otp}
GET /api/seller/profile
PATCH /api/seller/profile/update
Purpose:
Handles seller registration, login, email verification using OTP, and profile management.
4. Cart APIs
GET /api/cart
PUT /api/cart/add
DELETE /api/cart/item/{id}
PUT /api/cart/item/{id}
Purpose:
Manages cart operations like adding items, updating quantity, removing items, and fetching cart.
5. Product APIs
GET /api/products/{id}
GET /api/products/search
GET /api/products
Purpose:
Supports product retrieval, search, filtering, sorting, and pagination.
6. Category APIs
POST /api/categories
GET /api/categories
GET /api/categories/{id}
PUT /api/categories/{id}
DELETE /api/categories/{id}
Purpose:
Provides CRUD operations for product categories.
7. Order APIs
POST /api/orders
GET /api/orders/user
GET /api/orders/{id}
GET /api/orders/item/{id}
PUT /api/orders/{id}/cancel
Purpose:
Handles order creation, order history, fetching order details, and order cancellation.
8. Payment APIs
GET /api/payment/{paymentId}
Purpose:
Handles payment success flow and integrates with Razorpay and Stripe for payment links.
9. Transaction APIs
GET /api/transactions/seller
GET /api/transactions
Purpose:
Provides transaction history for sellers and overall system.
Key Design Points
Followed REST principles with resource-based URLs
Used appropriate HTTP methods (GET, POST, PUT, DELETE)
Implemented JWT authentication for security
Applied role-based access control (Customer, Seller, Admin)
Separated concerns using Controller, Service, Repository layers
One-Line Interview Summary
I designed modular REST APIs with proper HTTP methods, JWT-based authentication, and role-based access
control, covering all major e-commerce functionalities like user management, cart, orders, and payments.
Explain your Spring Security configuration”
Say this:
I configured Spring Security using SecurityFilterChain. I disabled CSRF for REST APIs and used stateless
session management with JWT. I defined role-based access using request matchers for public, authenticated,
seller, and admin APIs. I also added a custom JWT filter to validate tokens for every request.
CSRF → disabled
Session → stateless
CORS → frontend allowed
permitAll → public APIs
authenticated → login required
hasAuthority → role-based access
JWT filter → validate token
PasswordEncoder → hash password
Login → Generate JWT → Send to client
↓
Client sends JWT in header
↓
JwtTokenValidator intercepts request
↓
Extract user → Set authentication
↓
Controller executess