Marc Hauschildt
Web Technologies and Computer Software Development Instructor at Kirkwood Community College in Cedar Rapids, IA.
Week 10
<div class="d-flex justify-content-between align-items-center">
<small class="fw-bold"><fmt:formatNumber value="${product.price}" type="currency" /></small>
<form method="POST" action="${appURL}/add-to-cart" class=" w-75">
<input type="hidden" name="prod_id" value="${product.id}">
<div class="input-group">
<div class="form-floating">
<input type="number" min="0" class="form-control" id="quantity" name="quantity" value="1">
<label for="quantity">Qty</label>
</div>
<button type="submit" class="btn btn-outline-primary btn-sm">Add to Cart</button>
</div>
</form>
</div>
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/add-to-cart")
public class AddToCart extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String prodId = req.getParameter("prod_id");
String quantityStr = req.getParameter("quantity");
HttpSession session = req.getSession();
session.setAttribute("flashMessageSuccess", "Added to cart successfully");
resp.sendRedirect(resp.encodeRedirectURL(req.getContextPath() + "/shop"));
}
}
CREATE PROCEDURE sp_get_product(IN p_prod_id varchar(10))
BEGIN
SELECT prod_id, prod_name, prod_price, prod_desc
FROM products
WHERE prod_id = p_prod_id;
END;
// This constructor is for products in the shopping cart
public Product(String id, String name, double price, String description) {
this.id = id;
this.name = name;
this.price = price;
this.description = description;
}
public static Product get(String prod_id) {
Product product = null;
try(Connection connection = getConnection()) {
CallableStatement statement = connection.prepareCall("{call sp_get_product(?)}");
statement.setString(1, prod_id);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
String prodId = resultSet.getString("prod_id");
String prodName = resultSet.getString("prod_name");
double prodPrice = resultSet.getDouble("prod_price");
String prodDesc = resultSet.getString("prod_desc");
product = new Product(prodId, prodName, prodPrice, prodDesc);
}
} catch(SQLException e) {
throw new RuntimeException(e);
}
return product;
}
public static void main(String[] args) {
System.out.println(get("DOL001"));
}
@WebServlet("/add-to-cart")
public class AddToCart extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String prodId = req.getParameter("prod_id");
String quantityStr = req.getParameter("quantity");
boolean errorFound = false;
String errorMsg = "";
Product product = ProductDAO.get(prodId);
if(product == null){
errorFound = true;
errorMsg += "Invalid product\n";
}
HttpSession session = req.getSession();
if(errorFound){
session.setAttribute("flashMessageDanger", errorMsg);
} else {
session.setAttribute("flashMessageSuccess", "Added to cart successfully");
}
resp.sendRedirect(resp.encodeRedirectURL(req.getContextPath() + "/shop"));
}
}
@WebServlet("/add-to-cart")
public class AddToCart extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String prodId = req.getParameter("prod_id");
String quantityStr = req.getParameter("quantity");
boolean errorFound = false;
String errorMsg = "";
Product product = ProductDAO.get(prodId);
if(product == null){
errorFound = true;
errorMsg += "Invalid product\n";
}
int quantity = 0;
try {
quantity = Integer.parseInt(quantityStr);
if(quantity < 0){
errorFound = true;
errorMsg += "Quantity cannot be negative\n";
}
} catch (NumberFormatException e) {
errorFound = true;
errorMsg += "Invalid quantity";
}
HttpSession session = req.getSession();
if(errorFound){
session.setAttribute("flashMessageDanger", errorMsg);
} else {
session.setAttribute("flashMessageSuccess", "Added to cart successfully");
}
resp.sendRedirect(resp.encodeRedirectURL(req.getContextPath() + "/shop"));
}
}
import java.util.HashMap;
import java.util.Map;
public class ShoppingCart {
// Map to associate a product to quantity
private Map<Product, Integer> cartContents;
public ShoppingCart() {
cartContents = new HashMap<>();
}
// Method to add a product to a user's cart
public void addProduct(Product product, int quantity) {
if(product == null) {
throw new IllegalArgumentException("Product cannot be null");
}
if(quantity < 1) {
throw new IllegalArgumentException("Quantity cannot be less than 1");
}
contents.put(product, contents.getOrDefault(product, 0) + quantity);
}
// Method to view the cart contents
public Map<Product, Integer> getCartContents() {
return cartContents;
}
}
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Product product1 = ProductDAO.get("DOL001");
Product product2 = ProductDAO.get("BR02");
Product product3 = ProductDAO.get("DOL001");
cart.addProduct(product1, 1);
cart.addProduct(product2, 2);
cart.addProduct(product3, 3);
cart.getCartContents().entrySet().forEach(cartItem -> {
Product product = cartItem.getKey();
int quantity = cartItem.getValue();
double price = product.getPrice();
double totalPrice = price * quantity;
System.out.printf("%s, Qty: %d, Price: %.2f, Total: %.2f\n", product.getName(), quantity, price, totalPrice);
});
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
return Double.compare(price, product.price) == 0 && categoryId == product.categoryId && Objects.equals(id, product.id) && Objects.equals(name, product.name) && Objects.equals(description, product.description) && Objects.equals(vendorId, product.vendorId) && Objects.equals(vendorName, product.vendorName) && Objects.equals(categoryName, product.categoryName);
}
@Override
public int hashCode() {
return Objects.hash(id, name, price, description, vendorId, vendorName, categoryId, categoryName);
}
HttpSession session = req.getSession();
if(errorFound){
session.setAttribute("flashMessageDanger", errorMsg);
} else {
ShoppingCart cart = (ShoppingCart) session.getAttribute("cart");
if(cart == null){
cart = new ShoppingCart();
}
cart.addProduct(product, quantity);
session.setAttribute("cart", cart);
session.setAttribute("flashMessageSuccess", "Added to cart successfully");
}
// Method to return the total count of products in the cart
public int getTotalProductCount() {
int total = 0;
for (int quantity : cartContents.values()) {
total += quantity;
}
return total;
}
// Method to calculate the total cost of products in the cart
public double getTotalCost() {
double totalCost = 0.0;
for (Map.Entry<Product, Integer> entry : cartContents.entrySet()) {
Product product = entry.getKey();
int quantity = entry.getValue();
totalCost += product.getPrice() * quantity;
}
return totalCost;
}
<a href="${appURL}/cart" class="btn btn-primary me-2">
<i class="bi bi-cart"></i>
<c:if test="${not empty cart.totalProductCount}">${cart.totalProductCount}, </c:if>
<c:if test="${not empty cart.totalCost}"><fmt:formatNumber value="${cart.totalCost}" type="currency" /></c:if>
</a>
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/cart")
public class Cart extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("pageTitle", "Cart");
req.getRequestDispatcher("WEB-INF/ecommerce/cart.jsp").forward(req, resp);
}
}
<section class="h-100 h-custom bg-secondary">
<!-- Code omitted -->
<div class="d-flex justify-content-between align-items-center mb-5">
<h1 class="fw-bold mb-0">Shopping Cart</h1>
<h6 class="mb-0 text-muted">
<c:choose>
<c:when test="${not empty cart.totalProductCount}">${cart.totalProductCount} ${cart.totalProductCount eq 1 ? 'item' : 'items'}</c:when>
<c:otherwise>There are no products in your cart</c:otherwise>
</c:choose>
</h6>
</div>
<!-- Code omitted -->
<div class="pt-5">
<h6 class="mb-0"><a href="${appURL}/shop" class="text-body"><i
class="fas fa-long-arrow-alt-left me-2"></i>Back to shop</a></h6>
</div>
<!-- Code omitted -->
</section>
<c:forEach items="${cart.cartContents}" var="item">
<div class="row mb-4 d-flex justify-content-between align-items-center">
<div class="col-md-6">
<h6 class="mb-0">${item.key.name}</h6>
</div>
<div class="col-md-3">
<form method="POST" action="${appURL}/cart">
<input type="hidden" name="prod_id" value="${item.key.id}">
<div class="input-group">
<div class="form-floating">
<input type="number" min="0" class="form-control" id="quantity" name="quantity" value="${item.value}">
<label for="quantity">Qty</label>
</div>
<button type="submit" class="btn btn-outline-primary btn-sm">Update</button>
</div>
</form>
</div>
<div class="col-md-2 text-end">
<h6 class="mb-0"><fmt:formatNumber value="${item.key.price}" type="currency" /></h6>
</div>
<div class="col-md-1 text-end">
<a href="#!" class="text-muted"><i class="bi bi-trash"></i></a>
</div>
</div>
<hr class="my-4">
</c:forEach>
<c:if test="${not empty cart}">
<div class="p-5">
<h3 class="fw-bold mb-5 mt-2 pt-1">Summary</h3>
<hr class="my-4">
<div class="d-flex justify-content-between mb-4">
<h5 class="text-uppercase">subtotal</h5>
<h5><fmt:formatNumber value="${cart.totalCost}" type="currency" /></h5>
</div>
<c:set var="shipping" value="0" /><%-- Remove if you add a shipping calculation to the doPost method of the Cart servlet --%>
<div class="d-flex justify-content-between mb-4">
<h5 class="text-uppercase mb-3">Free Shipping</h5>
<h5><fmt:formatNumber value="0" type="currency" /></h5>
</div>
<hr class="my-4">
<div class="d-flex justify-content-between mb-5">
<h5 class="text-uppercase">Total price</h5>
<h5><fmt:formatNumber value="${cart.totalCost + shipping}" type="currency" /></h5>
</div>
<button type="button" data-mdb-button-init data-mdb-ripple-init class="btn btn-dark btn-block btn-lg"
data-mdb-ripple-color="dark">Check out</button>
</div>
</c:if>
public void updateProduct(Product product, int quantity) {
if(product == null) {
throw new IllegalArgumentException("Product cannot be null");
}
if(quantity < 1) {
throw new IllegalArgumentException("Quantity cannot be less than 1");
}
contents.put(product, quantity);
}
<form method="POST" action="${appURL}/cart" class="d-flex justify-content-center align-items-end">
<input type="hidden" name="prod_id" value="${entry.key.id}">
<input type="hidden" name="action" value="update">
<div class="input-group w-50">
<div class="">
<%-- entry.value refers to the Integer, the product quantity--%>
<input id="quantity" min="0" name="quantity" value="${entry.value}" type="number"
class="form-control form-control-sm" />
</div>
</div>
<button type="submit" class="btn btn-outline-primary btn-sm">Update</button>
</form>
public void deleteProduct(Product product) {
if(product == null) {
throw new IllegalArgumentException("Product cannot be null");
}
if(contents.containsKey(product)) {
contents.remove(product);
}
}
<form method="POST" action="${appURL}/cart" class="d-flex justify-content-center align-items-end">
<input type="hidden" name="prod_id" value="${entry.key.id}">
<input type="hidden" name="action" value="delete">
<button type="submit" class="text-muted"><i class="bi bi-trash"></i></button>
</form>
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
String prodId = req.getParameter("prod_id");
Product product = ProductDAO.getProduct(prodId);
HttpSession session = req.getSession();
ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
if(cart != null && product != null) {
}
req.setAttribute("pageTitle", "Cart");
req.getRequestDispatcher("WEB-INF/ecommerce/cart.jsp").forward(req, resp);
}
if (action.equals("update")) {
String quantityStr = req.getParameter("quantity");
int quantity = 1;
try {
quantity = Integer.parseInt(quantityStr);
if (quantity < 1) {
quantity = cart.getContents().get(product);
}
} catch (NumberFormatException e) {
// If error, keep whatever is in the cart
quantity = cart.getContents().get(product);
}
cart.updateProduct(product, quantity);
} else if (action.equals("delete")) {
cart.deleteProduct(product);
}
session.setAttribute("cart", cart);
By Marc Hauschildt
Web Technologies and Computer Software Development Instructor at Kirkwood Community College in Cedar Rapids, IA.