Migrate Pet controllers to REST API

This commit is contained in:
2026-03-07 13:28:45 -07:00
parent 58e29f307e
commit 87f616d08e
4 changed files with 125 additions and 155 deletions

View File

@@ -1,5 +1,6 @@
package org.example.petshopdesktop.controllers; package org.example.petshopdesktop.controllers;
import javafx.application.Platform;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@@ -10,16 +11,18 @@ import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.example.petshopdesktop.api.dto.pet.PetResponse;
import org.example.petshopdesktop.api.endpoints.PetApi;
import org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogController; import org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogController;
import org.example.petshopdesktop.database.PetDB;
import org.example.petshopdesktop.database.ProductDB;
import org.example.petshopdesktop.models.Pet; import org.example.petshopdesktop.models.Pet;
import org.example.petshopdesktop.util.ActivityLogger; import org.example.petshopdesktop.util.ActivityLogger;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.time.LocalDate;
import java.sql.SQLIntegrityConstraintViolationException; import java.time.Period;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
public class PetController { public class PetController {
@@ -83,48 +86,24 @@ public class PetController {
//if confirmed, start deletion //if confirmed, start deletion
if (result.isPresent() && result.get() == ButtonType.OK) { if (result.isPresent() && result.get() == ButtonType.OK) {
int successCount = 0; List<Long> ids = selectedPets.stream()
int failCount = 0; .map(p -> (long) p.getPetId())
StringBuilder errors = new StringBuilder(); .collect(Collectors.toList());
for (Pet pet : selectedPets) { try {
try{ PetApi.getInstance().deletePets(ids);
int numRows = PetDB.deletePet(pet.getPetId());
if (numRows > 0) {
successCount++;
} else {
failCount++;
}
}
catch (SQLIntegrityConstraintViolationException e){
ActivityLogger.getInstance().logException(
"PetController.btnDeleteClicked",
e,
String.format("Attempting to delete pet ID %d - foreign key constraint", pet.getPetId()));
failCount++;
errors.append("Pet '").append(pet.getPetName()).append("' is referenced in another table\n");
}
catch (SQLException e) {
ActivityLogger.getInstance().logException(
"PetController.btnDeleteClicked",
e,
String.format("Attempting to delete pet ID %d", pet.getPetId()));
failCount++;
errors.append("Failed to delete '").append(pet.getPetName()).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) {
Alert alert = new Alert(Alert.AlertType.INFORMATION); Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Database Operation Confirmed"); alert.setHeaderText("Database Operation Confirmed");
alert.setContentText("Successfully deleted " + successCount + " pet(s)"); alert.setContentText("Successfully deleted " + ids.size() + " pet(s)");
alert.showAndWait();
} catch (Exception e) {
ActivityLogger.getInstance().logException(
"PetController.btnDeleteClicked",
e,
"Deleting pets");
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Delete Operation Failed");
alert.setContentText(e.getMessage());
alert.showAndWait(); alert.showAndWait();
} }
@@ -187,39 +166,55 @@ public class PetController {
} }
private void displayFilteredPet(String filter) { private void displayFilteredPet(String filter) {
data.clear(); if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){
try{ displayPets();
if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){ } else {
displayPets(); new Thread(() -> {
} try {
else { List<PetResponse> pets = PetApi.getInstance().listPets(filter);
data = PetDB.getFilteredPets(filter); List<Pet> petList = pets.stream()
tvPets.setItems(data); .map(this::mapToPet)
} .collect(Collectors.toList());
} catch (Exception e) {
ActivityLogger.getInstance().logException( Platform.runLater(() -> {
"PetController.displayFilteredPet", data.setAll(petList);
e, tvPets.setItems(data);
"Filtering pets with filter: " + filter); });
System.out.println("Error while fetching table data: " + e.getMessage()); } catch (Exception e) {
Platform.runLater(() -> {
System.out.println("Error while fetching table data: " + e.getMessage());
ActivityLogger.getInstance().logException(
"PetController.displayFilteredPet",
e,
String.format("Filtering pets with keyword: %s", filter));
});
}
}).start();
} }
} }
private void displayPets() { private void displayPets() {
data.clear(); new Thread(() -> {
try {
List<PetResponse> pets = PetApi.getInstance().listPets(null);
List<Pet> petList = pets.stream()
.map(this::mapToPet)
.collect(Collectors.toList());
try{ Platform.runLater(() -> {
data = PetDB.getPets(); data.setAll(petList);
} tvPets.setItems(data);
catch(SQLException e){ });
ActivityLogger.getInstance().logException( } catch (Exception e) {
"PetController.displayPets", Platform.runLater(() -> {
e, System.out.println("Error while fetching table data: " + e.getMessage());
"Fetching pet data for table display"); ActivityLogger.getInstance().logException(
System.out.println("Error while fetching table data: " + e.getMessage()); "PetController.displayPets",
} e,
"Fetching pet data for table display");
tvPets.setItems(data); });
}
}).start();
} }
private void openDialog(Pet pet, String mode){ private void openDialog(Pet pet, String mode){
@@ -261,4 +256,20 @@ public class PetController {
txtSearch.setText(""); txtSearch.setText("");
} }
private Pet mapToPet(PetResponse response) {
int age = 0;
if (response.getDateOfBirth() != null) {
age = Period.between(response.getDateOfBirth(), LocalDate.now()).getYears();
}
return new Pet(
response.getId().intValue(),
response.getPetName(),
response.getSpecies(),
response.getBreed(),
age,
response.getPetStatus(),
response.getPrice().doubleValue()
);
}
} }

View File

@@ -21,7 +21,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors import java.util.stream.Collectors;
/** /**
* The controller for any operations in the products view * The controller for any operations in the products view
@@ -286,13 +286,14 @@ public class ProductController {
} }
private ProductDTO mapToProductDTO(ProductResponse response) { private ProductDTO mapToProductDTO(ProductResponse response) {
ProductDTO dto = new ProductDTO(); return new ProductDTO(
dto.setProdId(response.getId().intValue()); response.getId().intValue(),
dto.setProdName(response.getProductName()); response.getProductName(),
dto.setProdPrice(response.getPrice().doubleValue()); response.getPrice().doubleValue(),
dto.setCategoryName(response.getCategoryName()); 0,
dto.setProdDesc(response.getDescription()); response.getCategoryName(),
return dto; response.getDescription()
);
} }
} }

View File

@@ -8,14 +8,15 @@ import javafx.scene.Node;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.example.petshopdesktop.DTOs.ProductDTO;
import org.example.petshopdesktop.Validator; import org.example.petshopdesktop.Validator;
import org.example.petshopdesktop.database.PetDB; import org.example.petshopdesktop.api.dto.pet.PetRequest;
import org.example.petshopdesktop.models.Category; import org.example.petshopdesktop.api.dto.pet.PetResponse;
import org.example.petshopdesktop.api.endpoints.PetApi;
import org.example.petshopdesktop.models.Pet; import org.example.petshopdesktop.models.Pet;
import org.example.petshopdesktop.util.ActivityLogger; import org.example.petshopdesktop.util.ActivityLogger;
import java.sql.SQLException; import java.math.BigDecimal;
import java.time.LocalDate;
public class PetDialogController { public class PetDialogController {
@@ -77,7 +78,6 @@ public class PetDialogController {
} }
private void buttonSaveClicked(MouseEvent mouseEvent) { private void buttonSaveClicked(MouseEvent mouseEvent) {
int numRow = 0;
String errorMsg = ""; String errorMsg = "";
//Check validation (input required) //Check validation (input required)
@@ -102,46 +102,30 @@ public class PetDialogController {
errorMsg += Validator.isNonNegativeInteger(txtPetAge.getText(), "Age"); errorMsg += Validator.isNonNegativeInteger(txtPetAge.getText(), "Age");
if(errorMsg.isEmpty()){ if(errorMsg.isEmpty()){
Pet pet = collectPet(); PetRequest request = buildPetRequest();
if(mode.equals("Add")) { try {
try{ if(mode.equals("Add")) {
numRow = PetDB.insertPet(pet); PetApi.getInstance().createPet(request);
} else {
Long petId = Long.parseLong(lblPetId.getText().split(": ")[1]);
PetApi.getInstance().updatePet(petId, request);
} }
catch (SQLException e) {
ActivityLogger.getInstance().logException(
"PetDialogController.buttonSaveClicked",
e,
"Inserting new pet record");
throw new RuntimeException(e);
}
}
else {
try {
numRow = PetDB.updatePet(pet.getPetId(), pet);
}
catch (SQLException e) {
ActivityLogger.getInstance().logException(
"PetDialogController.buttonSaveClicked",
e,
"Updating pet with ID: " + pet.getPetId());
throw new RuntimeException(e);
}
}
//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 //tell the user operation was successful
Alert alert = new Alert(Alert.AlertType.INFORMATION); Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Saved"); alert.setHeaderText("Saved");
alert.setContentText(mode + " succeeded"); alert.setContentText(mode + " succeeded");
alert.showAndWait(); alert.showAndWait();
closeStage(mouseEvent); closeStage(mouseEvent);
} catch (Exception e) {
ActivityLogger.getInstance().logException(
"PetDialogController.buttonSaveClicked",
e,
mode + " pet record");
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Operation Error");
alert.setContentText(mode + " failed: " + e.getMessage());
alert.showAndWait();
} }
} }
else{ else{
@@ -152,23 +136,19 @@ public class PetDialogController {
} }
} }
private Pet collectPet() { private PetRequest buildPetRequest() {
int petId =0; PetRequest request = new PetRequest();
Pet pet = null; request.setPetName(txtPetName.getText());
request.setSpecies(txtPetSpecies.getText());
request.setBreed(txtPetBreed.getText());
request.setPetStatus(cbPetStatus.getValue());
request.setPrice(new BigDecimal(txtPetPrice.getText()));
if(lblPetId.isVisible()){ int age = Integer.parseInt(txtPetAge.getText());
petId = Integer.parseInt(lblPetId.getText().split(": ")[1]); LocalDate dateOfBirth = LocalDate.now().minusYears(age);
} request.setDateOfBirth(dateOfBirth);
pet = new Pet(
petId, return request;
txtPetName.getText(),
txtPetSpecies.getText(),
txtPetBreed.getText(),
Integer.parseInt(txtPetAge.getText()),
cbPetStatus.getValue(),
Double.parseDouble(txtPetPrice.getText())
);
return pet;
} }
private void closeStage(MouseEvent mouseEvent) { private void closeStage(MouseEvent mouseEvent) {

View File

@@ -17,7 +17,7 @@ import org.example.petshopdesktop.api.endpoints.ProductApi;
import org.example.petshopdesktop.util.ActivityLogger; import org.example.petshopdesktop.util.ActivityLogger;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List import java.util.List;
public class ProductDialogController { public class ProductDialogController {
@@ -145,28 +145,6 @@ public class ProductDialogController {
} }
} }
/**
* Collect the product info
* @return product info with the id or the new product
*/
private Product collectProduct(){
int prodId = 0;
Product product = null;
if(lblProdId.isVisible()){ //Edit mode
//get product id from lblId (split the string so we only get the int)
prodId = Integer.parseInt(lblProdId.getText().split(": ")[1]);
}
product = new Product(
prodId,
txtProdName.getText(),
Double.parseDouble(txtProdPrice.getText()),
cbProdCategory.getSelectionModel().getSelectedItem().getCategoryId(),
txtProdDesc.getText()
);
return product;
}
/** /**
* Display the product data in text fields and combobox * Display the product data in text fields and combobox
* @param product the product entity containing data to display * @param product the product entity containing data to display