sbnotes

Code with Spring Boot 3

Code with Spring Boot 3

Sr No. Topic
0 Project Structure 1
1 Project Structure 2
2 Project Structure 3

Project Structure 1 :

src
└── main
    ├── java
    │   └── com
    │       └── example
    │           ├──config
    │           ├──controllers
    │           ├──models
    │           ├──repo
    │           ├──service
    │           └──App.java
    └── resources
        └── application.properties

Step 1: Define the Model

Path : src/main/java/com/sp/product/Ecommerce/models

package com.sp.product.Ecommerce.models;

import java.util.List;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;

import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
public class Cart {
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Id
	private Integer cartId;
	private Double totalAmount;

	@OneToOne(fetch = FetchType.EAGER)
	@JsonIgnore
	private User user;

	@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER, mappedBy = "cart")
	private List<CartProduct> cartProducts;

	public Cart() {
		super();
	}

	public Cart(Integer cartId, Double totalAmount, User user, List<CartProduct> cartProducts) {
		super();
		this.cartId = cartId;
		this.totalAmount = totalAmount;
		this.user = user;
		this.cartProducts = cartProducts;
	}

	public Integer getCartId() {
		return cartId;
	}

	public void setCartId(Integer cartId) {
		this.cartId = cartId;
	}

	public Double getTotalAmount() {
		return totalAmount;
	}

	public void setTotalAmount(Double totalAmount) {
		this.totalAmount = totalAmount;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public List<CartProduct> getCartProducts() {
		return cartProducts;
	}

	public void setCartProducts(List<CartProduct> cartProducts) {
		this.cartProducts = cartProducts;
	}

	@Override
	public String toString() {
		return "Cart [cartId=" + cartId + ", totalAmount=" + totalAmount + ", user=" + user.getUserId()
				+ ", cartProducts=" + cartProducts + "]";
	}

	public void updateTotalAmount(Double price) {
		this.totalAmount += price;
	}
}
package com.sp.product.Ecommerce.models;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;

import com.fasterxml.jackson.annotation.JsonIgnore;

@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "cart_id", "product_id" }))
@Entity
public class CartProduct {
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Id
	private Integer cpId;
	@ManyToOne()
	@JoinColumn(name = "cart_id", referencedColumnName = "cartId")
	@JsonIgnore
	private Cart cart;
	@ManyToOne()
	@JoinColumn(name = "product_id", referencedColumnName = "productId")
	private Product product;
	private Integer quantity = 1;

	public CartProduct() {
		super();
	}

	public CartProduct(Cart cart, Product product, Integer quantity) {
		super();
		this.cart = cart;
		this.product = product;
		this.quantity = quantity;
	}

	public Integer getCpId() {
		return cpId;
	}

	public void setCpId(Integer cpId) {
		this.cpId = cpId;
	}

	public Cart getCart() {
		return cart;
	}

	public void setCart(Cart cart) {
		this.cart = cart;
	}

	public Product getProduct() {
		return product;
	}

	public void setProduct(Product product) {
		this.product = product;
	}

	public Integer getQuantity() {
		return quantity;
	}

	public void setQuantity(Integer quantity) {
		this.quantity = quantity;
	}

	@Override
	public String toString() {
		return "CartProduct [cpId=" + cpId + ", cart=" + cart.getCartId() + ", product=" + product.getProductId()
				+ ", quantity=" + quantity + "]";
	}

}
package com.sp.product.Ecommerce.models;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
public class Category {
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Id
	@JsonIgnore
	private Integer categoryId;
	@Column(unique = true)
	private String categoryName;

	public Category() {
		super();
	}

	public Category(String categoryName) {
		super();
		this.categoryName = categoryName;
	}

	public Integer getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(Integer categoryId) {
		this.categoryId = categoryId;
	}

	public String getCategoryName() {
		return categoryName;
	}

	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}

	@Override
	public String toString() {
		return "Category [categoryId=" + categoryId + ", categoryName=" + categoryName + "]";
	}

}
package com.sp.product.Ecommerce.models;

public class JWTrequest {
	String username;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	String password;

	public JWTrequest(String username, String password) {
		super();
		this.username = username;
		this.password = password;
	}

	public JWTrequest() {
		super();
	}
}
package com.sp.product.Ecommerce.models;

public class JWTresponse {
	String token;

	public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public JWTresponse(String token) {
		super();
		this.token = token;
	}

	public JWTresponse() {
		super();
	}
}
package com.sp.product.Ecommerce.models;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;

import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
public class Product {
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Id
	private Integer productId;
	private String productName;
	private Double price;
	@ManyToOne()
	@JoinColumn(name = "seller_id", referencedColumnName = "userId", updatable = false)
	@JsonIgnore
	private User seller;

	@ManyToOne()
	@JoinColumn(name = "category_id", referencedColumnName = "categoryId")
	private Category category;

	public Product() {
		super();
	}

	public Product(Integer productId, String productName, Double price, User seller, Category category) {
		super();
		this.productId = productId;
		this.productName = productName;
		this.price = price;
		this.seller = seller;
		this.category = category;
	}

	public Integer getProductId() {
		return productId;
	}

	public void setProductId(Integer productId) {
		this.productId = productId;
	}

	public String getProductName() {
		return productName;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

	public Double getPrice() {
		return price;
	}

	public void setPrice(Double price) {
		this.price = price;
	}

	public User getSeller() {
		return seller;
	}

	public void setSeller(User seller) {
		this.seller = seller;
	}

	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	@Override
	public String toString() {
		return "Product [productId=" + 0 + ", productName=" + productName + ", price=" + price + ", seller="
				+ seller.getUserId() + ", category=" + category + "]";
	}

}
package com.sp.product.Ecommerce.models;

import org.springframework.security.core.GrantedAuthority;

public enum Role {
	CONSUMER, SELLER;
}

class RoleGrantedAuthority implements GrantedAuthority {
	private static final long serialVersionUID = -3408298481881657796L;
	String role;

	public RoleGrantedAuthority(String role) {
		this.role = role;
	}

	@Override
	public String getAuthority() {
		return this.role;
	}

}
package com.sp.product.Ecommerce.models;

import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
public class User implements UserDetails {
	private static final long serialVersionUID = 5536306799835655715L;
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Id
	private Integer userId;
	@Column(unique = true)
	private String username;
	private String password;

	@ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
	@CollectionTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"))
	@Enumerated(EnumType.STRING)
	private Set<Role> roles;

	public User() {
		super();
	}

	public User(String username, String password, Set<Role> roles) {
		super();
		this.username = username;
		this.password = password;
		this.roles = roles;
	}

	public Integer getUserId() {
		return userId;
	}

	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	@Override
	public String toString() {
		return "User [userId=" + userId + ", username=" + username + ", password=" + password + ", roles=" + roles
				+ "]";
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return this.roles.stream().map(r -> new RoleGrantedAuthority(r.name())).collect(Collectors.toList());
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}

}

Step 2: Create the Repository

Path : src/main/java/com/sp/product/Ecommerce/repo

package com.sp.product.Ecommerce.repo;

import java.util.Optional;

import jakarta.transaction.Transactional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.sp.product.Ecommerce.models.CartProduct;

@Repository
public interface CartProductRepo extends JpaRepository<CartProduct, Integer> {
	Optional<CartProduct> findByCartUserUserIdAndProductProductId(Integer userId, Integer productId);

	@Transactional
	void deleteByCartUserUserIdAndProductProductId(Integer userId, Integer productId);
}
package com.sp.product.Ecommerce.repo;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.sp.product.Ecommerce.models.Cart;

@Repository
public interface CartRepo extends JpaRepository<Cart, Integer> {
	Optional<Cart> findByUserUsername(String username);
}
package com.sp.product.Ecommerce.repo;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.sp.product.Ecommerce.models.Category;

@Repository
public interface CategoryRepo extends JpaRepository<Category, Integer> {
	Optional<Category> findByCategoryName(String category);
}
package com.sp.product.Ecommerce.repo;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.sp.product.Ecommerce.models.Product;

@Repository
public interface ProductRepo extends JpaRepository<Product, Integer> {
	List<Product> findByProductNameContainingIgnoreCaseOrCategoryCategoryNameContainingIgnoreCase(String productName,
			String categoryName);

	List<Product> findBySellerUserId(Integer sellerId);

	Optional<Product> findBySellerUserIdAndProductId(Integer sellerId, Integer productId);
}
package com.sp.product.Ecommerce.repo;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.sp.product.Ecommerce.models.User;

@Repository
public interface UserRepo extends JpaRepository<User, Integer> {
	Optional<User> findByUsername(String username);
}

Step 3: Define the DTO

Step 4: Create the Service

Path : src/main/java/com/sp/product/Ecommerce/service

package com.sp.product.Ecommerce.service;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.sp.product.Ecommerce.models.User;
import com.sp.product.Ecommerce.repo.UserRepo;

@Service
public class UserAuthService implements UserDetailsService {
	@Autowired
	private UserRepo userRepo;

	public User loadUserByUserID(Integer id) {
		Optional<User> user = userRepo.findById(id);
		if (user.isPresent())
			return user.get();
		else
			throw new UsernameNotFoundException("User ID not found");
	}

	@Override
	public User loadUserByUsername(String username) throws UsernameNotFoundException {
		Optional<User> user = userRepo.findByUsername(username);
		if (user.isPresent())
			return user.get();
		else
			throw new UsernameNotFoundException("User ID not found");
	}
}

Step 5: Create the Controller

Path : src/main/java/com/sp/product/Ecommerce/controllers

package com.sp.product.Ecommerce.controllers;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.sp.product.Ecommerce.config.JwtUtil;
import com.sp.product.Ecommerce.models.Cart;
import com.sp.product.Ecommerce.models.CartProduct;
import com.sp.product.Ecommerce.models.Product;
import com.sp.product.Ecommerce.models.User;
import com.sp.product.Ecommerce.repo.CartProductRepo;
import com.sp.product.Ecommerce.repo.CartRepo;
import com.sp.product.Ecommerce.repo.CategoryRepo;
import com.sp.product.Ecommerce.repo.ProductRepo;
import com.sp.product.Ecommerce.repo.UserRepo;

@RestController
@RequestMapping("/api/auth/consumer")
public class ConsumerController {

	@Autowired
	CartRepo cartRepo;
	@Autowired
	CategoryRepo categoryRepo;
	@Autowired
	UserRepo userRepo;
	@Autowired
	ProductRepo productRepo;
	@Autowired
	CartProductRepo cpRepo;
	@Autowired
	private JwtUtil jwtUtil;

	@GetMapping("/cart")
	public ResponseEntity<Object> getCart(@RequestHeader("JWT") String jwt) {
		String username = jwtUtil.extractUsername(jwt);
		System.out.println(cartRepo.findByUserUsername(username).toString());

		return ResponseEntity.ok(cartRepo.findByUserUsername(username));
	}

	@PostMapping("/cart")
	public ResponseEntity<Object> postCart(@RequestHeader("JWT") String jwt, @RequestBody Product product) {
		String username = jwtUtil.extractUsername(jwt);
		Cart cart = cartRepo.findByUserUsername(username).get();
		Product prod = productRepo.findById(product.getProductId()).get();
		if (!cart.getCartProducts().stream().anyMatch(n -> n.getProduct().equals(prod))) {
			CartProduct cp = new CartProduct();
			cp.setCart(cart);
			cp.setProduct(prod);
			cp.setQuantity(1);
			cart.getCartProducts().add(cp);
			cart.updateTotalAmount(prod.getPrice() * cp.getQuantity());
			cartRepo.save(cart);
			return ResponseEntity.ok(cart);
		} else {
			return ResponseEntity.status(409).build();
		}
	}

	@PutMapping("/cart")
	public ResponseEntity<Object> putCart(@RequestHeader("JWT") String jwt, @RequestBody CartProduct cartProd) {
		String username = jwtUtil.extractUsername(jwt);
		User user = userRepo.findByUsername(username).orElse(null);
		Cart cart = cartRepo.findByUserUsername(username).orElse(null);
		if (user == null) {
			return ResponseEntity.badRequest().body("No user found");
		}
		Product prod = productRepo.findById(cartProd.getProduct().getProductId()).orElse(null);
		if (prod == null) {
			return ResponseEntity.badRequest().body("No product found");
		}
		CartProduct cp = cart.getCartProducts().stream().filter(n -> n.getProduct().equals(prod)).findFirst()
				.orElse(null);
		if (cp == null) {
			if (cartProd.getQuantity() > 0) {
				cp = new CartProduct();
				cp.setProduct(prod);
				cp.setQuantity(cartProd.getQuantity());
				cart.updateTotalAmount(prod.getPrice() * cartProd.getQuantity());
				cp.setCart(cart);
				cart.getCartProducts().add(cp);
			}
		} else {
			if (cartProd.getQuantity() == 0) {
				cart.getCartProducts().remove(cp);
				System.out.println(prod.getPrice() + "abc " + cartProd.getQuantity());
				cart.updateTotalAmount(-prod.getPrice() * cp.getQuantity());
				cpRepo.delete(cp);
			} else {
				cart.updateTotalAmount(prod.getPrice() * (cartProd.getQuantity() - cp.getQuantity()));
				cart.getCartProducts().get(cart.getCartProducts().indexOf(cp)).setQuantity(cartProd.getQuantity());
			}
		}
		cartRepo.saveAndFlush(cart);
		return ResponseEntity.ok(cart);

	}

	@DeleteMapping("/cart")
	public ResponseEntity<Object> deleteCart(@RequestHeader("JWT") String jwt, @RequestBody Product prod) {
		String username = jwtUtil.extractUsername(jwt);
		Cart cart = cartRepo.findByUserUsername(username).orElse(null);
		if (cart == null) {
			return ResponseEntity.badRequest().body("No cart found");
		}
		CartProduct cp = cart.getCartProducts().stream()
				.filter(n -> n.getProduct().getProductId().equals(prod.getProductId())).findFirst().orElse(null);
		if (cp == null) {
			return ResponseEntity.badRequest().body("No product found");
		}
		cart.getCartProducts().remove(cp);
		cart.updateTotalAmount(-cp.getProduct().getPrice() * cp.getQuantity());
		cpRepo.delete(cp);
		cartRepo.save(cart);
		return ResponseEntity.ok(cart);
	}

}
package com.sp.product.Ecommerce.controllers;

public class MyExceptionHandler {

}
package com.sp.product.Ecommerce.controllers;

import java.util.List;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.sp.product.Ecommerce.config.JwtUtil;
import com.sp.product.Ecommerce.models.JWTrequest;
import com.sp.product.Ecommerce.models.Product;
import com.sp.product.Ecommerce.repo.ProductRepo;

@RestController
@RequestMapping("/api/public")
public class PublicController {

	@Autowired
	AuthenticationManager auth;

	@Autowired
	JwtUtil jwtUtil;

	@Autowired
	ProductRepo prodRepo;

	@GetMapping("/product/search")
	public List<Product> getProducts(@RequestParam("keyword") String keyword) {
 		return prodRepo.findByProductNameContainingIgnoreCaseOrCategoryCategoryNameContainingIgnoreCase(keyword, keyword);
	}

	@PostMapping("/login")
	public ResponseEntity<String> login(@RequestBody JWTrequest request) {
 		try {
			auth.authenticate(new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
		}
		String token = jwtUtil.generateToken(request.getUsername());
		return ResponseEntity.ok(token);
	}

}
package com.sp.product.Ecommerce.controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.sp.product.Ecommerce.config.JwtUtil;
import com.sp.product.Ecommerce.models.Category;
import com.sp.product.Ecommerce.models.Product;
import com.sp.product.Ecommerce.models.User;
import com.sp.product.Ecommerce.repo.CartProductRepo;
import com.sp.product.Ecommerce.repo.CartRepo;
import com.sp.product.Ecommerce.repo.CategoryRepo;
import com.sp.product.Ecommerce.repo.ProductRepo;
import com.sp.product.Ecommerce.repo.UserRepo;

@RestController
@RequestMapping("/api/auth/seller")
public class SellerController {

	@Autowired
	ProductRepo productRepo;
	@Autowired
	CartRepo cartRepo;
	@Autowired
	CategoryRepo categoryRepo;
	@Autowired
	UserRepo userRepo;
	@Autowired
	CartProductRepo cpRepo;
	@Autowired
	private JwtUtil jwtUtil;

	@PostMapping("/product")
	public ResponseEntity<Object> postProduct(@RequestHeader("JWT") String jwt, @RequestBody Product product) {
		User user = userRepo.findByUsername(jwtUtil.extractUsername(jwt)).orElse(null);
		if (user == null) {
			return ResponseEntity.badRequest().body("No user found");
		}
		Category category = categoryRepo.findByCategoryName(product.getCategory().getCategoryName()).get();
		if (category == null) {
			return ResponseEntity.badRequest().body("No user found");
		}
		product.setSeller(user);
		product.setCategory(category);
		productRepo.saveAndFlush(product);
		return ResponseEntity.ok(product);
//		return ResponseEntity.status(HttpStatus.CREATED).body("http://localhost/api/auth/seller/product/" + product.getProductId());

	}

	@GetMapping("/product")
	public ResponseEntity<Object> getAllProducts(@RequestHeader("JWT") String jwt) {
		String username = jwtUtil.extractUsername(jwt);
		User user = userRepo.findByUsername(username).orElse(null);
		if (user == null) {
			return ResponseEntity.badRequest().body("No user found");
		}
		List<Product> list = productRepo.findBySellerUserId(user.getUserId());
		return ResponseEntity.ok(list);
	}

	@GetMapping("/product/{productId}")
	public ResponseEntity<Object> getProduct(@RequestHeader("JWT") String jwt, @PathVariable Integer productId) {
		String username = jwtUtil.extractUsername(jwt);
		User user = userRepo.findByUsername(username).orElse(null);
		if (user == null) {
			return ResponseEntity.badRequest().body("No user found");
		}
		Product prod = productRepo.findBySellerUserIdAndProductId(user.getUserId(), productId).orElse(null);
		return ResponseEntity.ok(prod);
	}

	@PutMapping("/product")
	public ResponseEntity<Object> putProduct(@RequestHeader("JWT") String jwt, @RequestBody Product product) {
		String username = jwtUtil.extractUsername(jwt);
		User user = userRepo.findByUsername(username).orElse(null);
		if (user == null) {
			return ResponseEntity.badRequest().body("No user found");
		}
		Product prod = productRepo.findBySellerUserIdAndProductId(user.getUserId(), product.getProductId())
				.orElse(null);
		Category category = categoryRepo.findByCategoryName(product.getCategory().getCategoryName()).get();
		if (prod == null) {
			return ResponseEntity.badRequest().body("No product found");
		}
		if (category == null) {
			return ResponseEntity.badRequest().body("No Category found");
		}
		prod.setProductName(product.getProductName());
		prod.setPrice(product.getPrice());
		prod.setCategory(category);
		productRepo.saveAndFlush(prod);
		return ResponseEntity.ok(prod);
	}

	@DeleteMapping("/product/{productId}")
	public ResponseEntity<Product> deleteProduct(@RequestHeader("JWT") String jwt, @PathVariable Integer productId) {
		String username = jwtUtil.extractUsername(jwt);
		User user = userRepo.findByUsername(username).orElse(null);
		if (user == null) {
			return ResponseEntity.badRequest().body(null);
		}
		System.out.println(productId);
		Product product = productRepo.findBySellerUserIdAndProductId(user.getUserId(), productId).orElse(null);
		if (product == null) {
			return ResponseEntity.status(404).body(null);
		}
		productRepo.delete(product);
		return ResponseEntity.ok(product);

	}
}

Step 6: Configure Security

Path : src/main/java/com/sp/product/Ecommerce/config

package com.sp.product.Ecommerce.config;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

@Component
public class ApiAuthenticationEntryPoint implements AuthenticationEntryPoint {
	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authException) throws IOException, ServletException {
		response.sendError(401, "unautherized");
	}
}
package com.sp.product.Ecommerce.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.sp.product.Ecommerce.service.UserAuthService;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class ApiSecurityConfig {

	@Autowired
	JwtAuthenticationFilter filter;
	@Autowired
	ApiAuthenticationEntryPoint entryPoint;
	@Autowired
	UserAuthService userDetails;

//	@Override
//	public void configure(WebSecurity web) throws Exception {
//
//	}


	@Bean
	public PasswordEncoder getPasswordEndcoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration)
			throws Exception {
		return authenticationConfiguration.getAuthenticationManager();
	}


    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

             http.csrf(csrf -> csrf.disable())
            .exceptionHandling(exp -> exp.authenticationEntryPoint(entryPoint))
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
            .requestMatchers("/api/public/**").permitAll()
            .requestMatchers("/api/auth/consumer/**").hasAnyAuthority("CONSUMER")
            .requestMatchers("/api/auth/seller/**").hasAnyAuthority("SELLER")
            .anyRequest()
            .authenticated());


            http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);

            return http.build();
    }


//	@Bean
//	public RegistrationBean jwtAuthFilterRegister(JwtAuthenticationFilter filter) {
//		return null;
//	}
}
package com.sp.product.Ecommerce.config;

import java.io.IOException;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.sp.product.Ecommerce.service.UserAuthService;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

	@Autowired
	JwtUtil jwtUtil;

	@Autowired
	UserAuthService userDetails;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		String header = request.getHeader("Authorization");
		String token = null, username = null;
		UserDetails user = null;
		if (header != null && header.startsWith("Bearer")) {
			token = header.substring(7);
			username = jwtUtil.extractUsername(token);
		}

		if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
			user = userDetails.loadUserByUsername(username);

			if (user != null && jwtUtil.validateToken(token, user)) {

				UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null,
						user.getAuthorities());
				auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
				SecurityContextHolder.getContext().setAuthentication(auth);
			}
		}
		filterChain.doFilter(request, response);
	}
}
package com.sp.product.Ecommerce.config;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import com.sp.product.Ecommerce.models.User;
import com.sp.product.Ecommerce.service.UserAuthService;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Component
public class JwtUtil {
	@Autowired
	UserAuthService userDetails;

	public User getUser(final String token) {
		String username = extractUsername(token);
		return userDetails.loadUserByUsername(username);
	}

	public String generateToken(String username) {
 		Map<String, Object> claims = new HashMap<>();
		return Jwts.builder()
				.setClaims(claims)
				.setSubject(username)
				.setIssuedAt(new Date())
				.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 2))
				.signWith(SignatureAlgorithm.HS256, "secret").compact();

	}

	public boolean validateToken(final String token,UserDetails user) {
  		return  user.getUsername().equals(extractUsername(token)) && extractExpiration(token).after(new Date());
	}

	public Claims extractClaims(String token) {
		return Jwts.parser().setSigningKey("secret").parseClaimsJws(token).getBody();
	}

	public Date extractExpiration(final String token) {
		return extractClaims(token).getExpiration();
	}

	public String extractUsername(final String token) {
		return extractClaims(token).getSubject();
	}
}

Step 7: Application Properties

src/main/resources/application.properties


spring.application.name=Ecommerce
server.port=8000

spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.initialization-mode=always

jwt.secret=secretkey
jwt.token.validity=900000

src/main/resources/data.sql

INSERT INTO category ("CATEGORY_NAME") VALUES ('Fashion');

INSERT INTO user ("USERNAME", "PASSWORD") VALUES ('John', 'pass_word');

INSERT INTO cart ("TOTAL_AMOUNT", "USER_USER_ID" ) VALUES (20, 1);

INSERT INTO USER_ROLE ("USER_ID", "ROLES") VALUES (1, 'CONSUMER');

INSERT INTO PRODUCT ("PRICE", "PRODUCT_NAME", "CATEGORY_ID", "SELLER_ID") VALUES (29190, 'Apple MacBook', 2, 3);

INSERT INTO CART_PRODUCT ("CART_ID", "PRODUCT_ID", "QUANTITY") VALUES (1, 2, 2);

When developing a Spring Boot application, it’s essential to understand the flow and the order in which files are typically created and referenced. Below is a step-by-step guide to creating the necessary files for a CRUD REST API, explaining how each file is referenced in the overall architecture.

Flow of Creation

  1. Model: Start by defining the data structure of your entities. The Employee class is created first as it defines what data you are working with.

  2. Repository: Next, create the repository interface. The repository will manage the CRUD operations for the Employee model.

  3. Service: Create the service layer. The service contains the business logic and interacts with the repository to perform CRUD operations.

  4. Controller: Create the controller that will handle HTTP requests and responses. The controller will use the service to get the necessary data and return it to the client.

  5. Configuration: Finally, configure security settings if needed. This step can be done at any time after the basic CRUD operations are functional.

Summary

  1. Model: Defines the data structure.
  2. Repository: Manages CRUD operations for the model.
  3. Service: Contains business logic and interacts with the repository.
  4. Controller: Handles HTTP requests and interacts with the service.
  5. Configuration: Sets up security and other configurations.

Each layer references the previous ones:

Project Structure 2 :

Project Structure 3 :