From 58e29f307e565a1ebfa10b90dbe74170cae48a51 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Sat, 7 Mar 2026 13:23:16 -0700 Subject: [PATCH] Migrate Product controllers to REST API --- .../controllers/ProductController.java | 152 +++++++++--------- .../ProductDialogController.java | 86 +++++----- 2 files changed, 112 insertions(+), 126 deletions(-) diff --git a/src/main/java/org/example/petshopdesktop/controllers/ProductController.java b/src/main/java/org/example/petshopdesktop/controllers/ProductController.java index abc38be7..90cc0775 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/ProductController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/ProductController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -11,18 +12,16 @@ import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Modality; import javafx.stage.Stage; import org.example.petshopdesktop.DTOs.ProductDTO; +import org.example.petshopdesktop.api.dto.product.ProductResponse; +import org.example.petshopdesktop.api.endpoints.ProductApi; import org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController; -import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController; -import org.example.petshopdesktop.database.ProductDB; -import org.example.petshopdesktop.database.SupplierDB; -import org.example.petshopdesktop.models.Product; -import org.example.petshopdesktop.models.Supplier; import org.example.petshopdesktop.util.ActivityLogger; import java.io.IOException; -import java.sql.SQLException; -import java.sql.SQLIntegrityConstraintViolationException; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors /** * The controller for any operations in the products view @@ -110,22 +109,27 @@ public class ProductController { * Display the productDTO to table view */ private void displayProduct(){ - //Erase old content - data.clear(); + new Thread(() -> { + try { + List products = ProductApi.getInstance().listProducts(null); + List productDTOs = products.stream() + .map(this::mapToProductDTO) + .collect(Collectors.toList()); - //get Products from database - try{ - data = ProductDB.getProductDTO(); - } catch (SQLException e) { - System.out.println("Error while fetching table data: " + e.getMessage()); - ActivityLogger.getInstance().logException( - "ProductController.displayProduct", - e, - "Fetching product data for table display"); - } - - //put data in the table - tvProducts.setItems(data); + Platform.runLater(() -> { + data.setAll(productDTOs); + tvProducts.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "ProductController.displayProduct", + e, + "Fetching product data for table display"); + }); + } + }).start(); } /** @@ -160,48 +164,24 @@ public class ProductController { //if confirmed, start deletion if (result.isPresent() && result.get() == ButtonType.OK) { - int successCount = 0; - int failCount = 0; - StringBuilder errors = new StringBuilder(); + List ids = selectedProducts.stream() + .map(p -> (long) p.getProdId()) + .collect(Collectors.toList()); - for (ProductDTO product : selectedProducts) { - try{ - int numRows = ProductDB.deleteProduct(product.getProdId()); - if (numRows > 0) { - successCount++; - } else { - failCount++; - } - } - catch (SQLIntegrityConstraintViolationException e){ - ActivityLogger.getInstance().logException( - "ProductController.btnDeleteClicked", - e, - String.format("Attempting to delete product ID %d - foreign key constraint", product.getProdId())); - failCount++; - errors.append("Product '").append(product.getProdName()).append("' is referenced in another table\n"); - } - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "ProductController.btnDeleteClicked", - e, - String.format("Attempting to delete product ID %d", product.getProdId())); - failCount++; - errors.append("Failed to delete '").append(product.getProdName()).append("'\n"); - } - } - - //show results - if (failCount > 0) { - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setHeaderText("Delete Operation Completed with Errors"); - alert.setContentText(String.format("Deleted: %d\nFailed: %d\n\n%s", - successCount, failCount, errors.toString())); - alert.showAndWait(); - } else if (successCount > 0) { + try { + ProductApi.getInstance().deleteProducts(ids); Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Database Operation Confirmed"); - alert.setContentText("Successfully deleted " + successCount + " product(s)"); + alert.setContentText("Successfully deleted " + ids.size() + " product(s)"); + alert.showAndWait(); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "ProductController.btnDeleteClicked", + e, + "Deleting products"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Delete Operation Failed"); + alert.setContentText(e.getMessage()); alert.showAndWait(); } @@ -233,22 +213,30 @@ public class ProductController { * @param filter word to filter table */ private void displayFilteredProduct(String filter){ - data.clear(); - try{ - if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){ - displayProduct(); //If search bar is empty just display everything - } - else{ - //Filter the using the keyword - data = ProductDB.getFilteredProductDTOs(filter); - tvProducts.setItems(data); - } - } catch (Exception e) { - System.out.println("Error while fetching table data: " + e.getMessage()); - ActivityLogger.getInstance().logException( - "ProductController.displayFilteredProduct", - e, - String.format("Filtering products with keyword: %s", filter)); + if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){ + displayProduct(); + } else { + new Thread(() -> { + try { + List products = ProductApi.getInstance().listProducts(filter); + List productDTOs = products.stream() + .map(this::mapToProductDTO) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + data.setAll(productDTOs); + tvProducts.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "ProductController.displayFilteredProduct", + e, + String.format("Filtering products with keyword: %s", filter)); + }); + } + }).start(); } } @@ -297,4 +285,14 @@ public class ProductController { txtSearch.setText(""); } + private ProductDTO mapToProductDTO(ProductResponse response) { + ProductDTO dto = new ProductDTO(); + dto.setProdId(response.getId().intValue()); + dto.setProdName(response.getProductName()); + dto.setProdPrice(response.getPrice().doubleValue()); + dto.setCategoryName(response.getCategoryName()); + dto.setProdDesc(response.getDescription()); + return dto; + } + } diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductDialogController.java index 5ad23f81..a63216be 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductDialogController.java @@ -10,15 +10,14 @@ import javafx.scene.input.MouseEvent; import javafx.stage.Stage; import org.example.petshopdesktop.DTOs.ProductDTO; import org.example.petshopdesktop.Validator; -import org.example.petshopdesktop.database.CategoryDB; -import org.example.petshopdesktop.database.ProductDB; -import org.example.petshopdesktop.models.Category; -import org.example.petshopdesktop.models.Product; -import org.example.petshopdesktop.models.Supplier; +import org.example.petshopdesktop.api.dto.common.DropdownOption; +import org.example.petshopdesktop.api.dto.product.ProductRequest; +import org.example.petshopdesktop.api.endpoints.DropdownApi; +import org.example.petshopdesktop.api.endpoints.ProductApi; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; -import java.util.ArrayList; +import java.math.BigDecimal; +import java.util.List public class ProductDialogController { @@ -29,7 +28,7 @@ public class ProductDialogController { private Button btnSave; @FXML - private ComboBox cbProdCategory; + private ComboBox cbProdCategory; @FXML private Label lblMode; @@ -70,11 +69,10 @@ public class ProductDialogController { //Set up combobox for selecting category try { - //set up combobox - ObservableList categories = FXCollections.observableArrayList(); //empty list - categories = CategoryDB.getCategories(); - cbProdCategory.setItems(categories); - } catch (SQLException e) { + List categories = DropdownApi.getInstance().getCategories(); + ObservableList categoriesObs = FXCollections.observableArrayList(categories); + cbProdCategory.setItems(categoriesObs); + } catch (Exception e) { ActivityLogger.getInstance().logException( "ProductDialogController.initialize", e, @@ -108,45 +106,35 @@ public class ProductDialogController { //Check Validation (format) errorMsg += Validator.isNonNegativeDouble(txtProdPrice.getText(), "Product Price"); - if (errorMsg.isEmpty()) { //no validation errors detected - Product product = collectProduct(); //get product info - if (mode.equals("Add")){ //add mode - try{ - numRow = ProductDB.insertProduct(product); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "ProductDialogController.buttonSaveClicked", - e, - "Inserting new product record"); - throw new RuntimeException(e); - } - } - else { //edit - try{ - numRow = ProductDB.updateProduct(product.getProdId(),product); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "ProductDialogController.buttonSaveClicked", - e, - "Updating product with ID: " + product.getProdId()); - throw new RuntimeException(e); - } - } + if (errorMsg.isEmpty()) { + try { + ProductRequest request = new ProductRequest(); + request.setProductName(txtProdName.getText()); + request.setPrice(new BigDecimal(txtProdPrice.getText())); + request.setCategoryId(cbProdCategory.getSelectionModel().getSelectedItem().getId()); + request.setDescription(txtProdDesc.getText()); + + if (mode.equals("Add")) { + ProductApi.getInstance().createProduct(request); + } else { + Long productId = Long.parseLong(lblProdId.getText().split(": ")[1]); + ProductApi.getInstance().updateProduct(productId, request); + } - //if no rows were affected then there was an error (prompt user of error) - if (numRow == 0){ - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Database Operation Error"); - alert.setContentText(mode + " failed"); - alert.showAndWait(); - } - else { - //tell the user operation was successful Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Saved"); alert.setContentText(mode + " succeeded"); alert.showAndWait(); closeStage(mouseEvent); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "ProductDialogController.buttonSaveClicked", + e, + mode + " product"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Database Operation Error"); + alert.setContentText(e.getMessage()); + alert.showAndWait(); } } else{ //Display validation errors @@ -190,10 +178,10 @@ public class ProductDialogController { txtProdDesc.setText(product.getProdDesc()); txtProdPrice.setText(product.getProdPrice() + ""); - //get the right combobox selection - for (Category category : cbProdCategory.getItems()) { - if(category.getCategoryId() == product.getCategoryId()){ + for (DropdownOption category : cbProdCategory.getItems()) { + if(category.getLabel().equals(product.getCategoryName())){ cbProdCategory.getSelectionModel().select(category); + break; } }