Migrate Product controllers to REST API

This commit is contained in:
2026-03-07 13:23:16 -07:00
parent 4fc518af07
commit 58e29f307e
2 changed files with 112 additions and 126 deletions

View File

@@ -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<ProductResponse> products = ProductApi.getInstance().listProducts(null);
List<ProductDTO> 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<Long> 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<ProductResponse> products = ProductApi.getInstance().listProducts(filter);
List<ProductDTO> 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;
}
}

View File

@@ -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<Category> cbProdCategory;
private ComboBox<DropdownOption> cbProdCategory;
@FXML
private Label lblMode;
@@ -70,11 +69,10 @@ public class ProductDialogController {
//Set up combobox for selecting category
try {
//set up combobox
ObservableList<Category> categories = FXCollections.observableArrayList(); //empty list
categories = CategoryDB.getCategories();
cbProdCategory.setItems(categories);
} catch (SQLException e) {
List<DropdownOption> categories = DropdownApi.getInstance().getCategories();
ObservableList<DropdownOption> 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;
}
}