From 59de8ae1aa6dd5f7da81ed97cd88b4d91977597e Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Sun, 8 Mar 2026 10:05:09 -0600 Subject: [PATCH] Fix null pointers and unsafe parsing bugs --- .../example/petshopdesktop/api/ApiClient.java | 23 +++++++++++ .../api/endpoints/AdoptionApi.java | 16 ++++++-- .../api/endpoints/AppointmentApi.java | 16 ++++++-- .../api/endpoints/DropdownApi.java | 35 +++++++++++++---- .../api/endpoints/InventoryApi.java | 16 ++++++-- .../petshopdesktop/api/endpoints/PetApi.java | 16 ++++++-- .../api/endpoints/ProductApi.java | 16 ++++++-- .../api/endpoints/ProductSupplierApi.java | 16 ++++++-- .../api/endpoints/PurchaseOrderApi.java | 16 ++++++-- .../petshopdesktop/api/endpoints/SaleApi.java | 16 ++++++-- .../api/endpoints/ServiceApi.java | 16 ++++++-- .../api/endpoints/SupplierApi.java | 16 ++++++-- .../petshopdesktop/api/endpoints/UserApi.java | 16 ++++++-- .../controllers/LoginController.java | 12 +++++- .../AdoptionDialogController.java | 27 ++++++++++--- .../AppointmentDialogController.java | 38 ++++++++++++++----- .../InventoryDialogController.java | 36 ++++++++++++------ .../PetDialogController.java | 19 ++++++++-- .../ProductDialogController.java | 22 ++++++++--- .../ProductSupplierDialogController.java | 14 +++++-- .../SupplierDialogController.java | 6 ++- 21 files changed, 328 insertions(+), 80 deletions(-) diff --git a/src/main/java/org/example/petshopdesktop/api/ApiClient.java b/src/main/java/org/example/petshopdesktop/api/ApiClient.java index 9563fae3..a2e0e279 100644 --- a/src/main/java/org/example/petshopdesktop/api/ApiClient.java +++ b/src/main/java/org/example/petshopdesktop/api/ApiClient.java @@ -44,6 +44,28 @@ public class ApiClient { return handleResponse(response, responseClass); } + public String getRawResponse(String path) throws Exception { + HttpRequest.Builder builder = HttpRequest.newBuilder() + .uri(URI.create(baseUrl + path)) + .GET() + .timeout(Duration.ofSeconds(30)); + + addAuthHeader(builder); + + HttpRequest request = builder.build(); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + + if (response.statusCode() == 200 || response.statusCode() == 201) { + return response.body(); + } else if (response.statusCode() == 401) { + throw new RuntimeException("Authentication failed. Please log in again."); + } else if (response.statusCode() == 403) { + throw new RuntimeException("Access restricted. You don't have permission to perform this action."); + } else { + throw new RuntimeException(parseErrorMessage(response)); + } + } + public T post(String path, Object requestBody, Class responseClass) throws Exception { String jsonBody = objectMapper.writeValueAsString(requestBody); @@ -155,6 +177,7 @@ public class ApiClient { } } } catch (Exception e) { + System.err.println("Error parsing error message: " + e.getMessage()); } return "Request failed with status " + response.statusCode(); } diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/AdoptionApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/AdoptionApi.java index f5c0f8e4..d4f90c85 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/AdoptionApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/AdoptionApi.java @@ -5,7 +5,10 @@ import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.adoption.AdoptionRequest; import org.example.petshopdesktop.api.dto.adoption.AdoptionResponse; import org.example.petshopdesktop.api.dto.common.BulkDeleteRequest; +import org.example.petshopdesktop.api.dto.common.PageResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class AdoptionApi { @@ -23,10 +26,17 @@ public class AdoptionApi { public List listAdoptions(String query) throws Exception { String path = "/api/v1/adoptions?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from adoptions endpoint"); + } + return pageResponse.getContent(); } public AdoptionResponse createAdoption(AdoptionRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/AppointmentApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/AppointmentApi.java index e7d1410a..4dd65bf0 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/AppointmentApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/AppointmentApi.java @@ -5,7 +5,10 @@ import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.appointment.AppointmentRequest; import org.example.petshopdesktop.api.dto.appointment.AppointmentResponse; import org.example.petshopdesktop.api.dto.common.BulkDeleteRequest; +import org.example.petshopdesktop.api.dto.common.PageResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class AppointmentApi { @@ -23,10 +26,17 @@ public class AppointmentApi { public List listAppointments(String query) throws Exception { String path = "/api/v1/appointments?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from appointments endpoint"); + } + return pageResponse.getContent(); } public AppointmentResponse createAppointment(AppointmentRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java index bff7998c..6c20526e 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java @@ -19,37 +19,58 @@ public class DropdownApi { } public List getCategories() throws Exception { - String response = apiClient.get("/api/v1/dropdowns/categories", String.class); + String response = apiClient.getRawResponse("/api/v1/dropdowns/categories"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from categories endpoint"); + } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } public List getProducts() throws Exception { - String response = apiClient.get("/api/v1/dropdowns/products", String.class); + String response = apiClient.getRawResponse("/api/v1/dropdowns/products"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from products endpoint"); + } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } public List getSuppliers() throws Exception { - String response = apiClient.get("/api/v1/dropdowns/suppliers", String.class); + String response = apiClient.getRawResponse("/api/v1/dropdowns/suppliers"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from suppliers endpoint"); + } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } public List getServices() throws Exception { - String response = apiClient.get("/api/v1/dropdowns/services", String.class); + String response = apiClient.getRawResponse("/api/v1/dropdowns/services"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from services endpoint"); + } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } public List getCustomers() throws Exception { - String response = apiClient.get("/api/v1/dropdowns/customers", String.class); + String response = apiClient.getRawResponse("/api/v1/dropdowns/customers"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from customers endpoint"); + } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } public List getPets() throws Exception { - String response = apiClient.get("/api/v1/dropdowns/pets", String.class); + String response = apiClient.getRawResponse("/api/v1/dropdowns/pets"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from pets endpoint"); + } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } public List getStores() throws Exception { - String response = apiClient.get("/api/v1/dropdowns/stores", String.class); + String response = apiClient.getRawResponse("/api/v1/dropdowns/stores"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from stores endpoint"); + } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } } diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/InventoryApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/InventoryApi.java index 1712576e..dbf08be7 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/InventoryApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/InventoryApi.java @@ -2,9 +2,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.inventory.InventoryRequest; import org.example.petshopdesktop.api.dto.inventory.InventoryResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class InventoryApi { @@ -22,10 +25,17 @@ public class InventoryApi { public List listInventory(String query) throws Exception { String path = "/api/v1/inventory?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from inventory endpoint"); + } + return pageResponse.getContent(); } public InventoryResponse createInventory(InventoryRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/PetApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/PetApi.java index 73b2c55c..b5fe23e9 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/PetApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/PetApi.java @@ -3,9 +3,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.common.BulkDeleteRequest; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.pet.PetRequest; import org.example.petshopdesktop.api.dto.pet.PetResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class PetApi { @@ -23,10 +26,17 @@ public class PetApi { public List listPets(String query) throws Exception { String path = "/api/v1/pets?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from pets endpoint"); + } + return pageResponse.getContent(); } public PetResponse createPet(PetRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/ProductApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/ProductApi.java index 3a40ec76..5bffd489 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/ProductApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/ProductApi.java @@ -3,9 +3,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.common.BulkDeleteRequest; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.product.ProductRequest; import org.example.petshopdesktop.api.dto.product.ProductResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class ProductApi { @@ -23,10 +26,17 @@ public class ProductApi { public List listProducts(String query) throws Exception { String path = "/api/v1/products?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from products endpoint"); + } + return pageResponse.getContent(); } public ProductResponse createProduct(ProductRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/ProductSupplierApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/ProductSupplierApi.java index b98c3d74..ea65becf 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/ProductSupplierApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/ProductSupplierApi.java @@ -3,9 +3,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.common.BulkDeleteRequest; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierRequest; import org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class ProductSupplierApi { @@ -23,10 +26,17 @@ public class ProductSupplierApi { public List listProductSuppliers(String query) throws Exception { String path = "/api/v1/product-suppliers?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from product-suppliers endpoint"); + } + return pageResponse.getContent(); } public ProductSupplierResponse createProductSupplier(ProductSupplierRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/PurchaseOrderApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/PurchaseOrderApi.java index 3b9cd558..accea0eb 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/PurchaseOrderApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/PurchaseOrderApi.java @@ -2,8 +2,11 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.purchaseorder.PurchaseOrderResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class PurchaseOrderApi { @@ -21,9 +24,16 @@ public class PurchaseOrderApi { public List listPurchaseOrders(String query) throws Exception { String path = "/api/v1/purchase-orders?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from purchase-orders endpoint"); + } + return pageResponse.getContent(); } } diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/SaleApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/SaleApi.java index f1e18733..d3355012 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/SaleApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/SaleApi.java @@ -2,9 +2,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.sale.SaleRequest; import org.example.petshopdesktop.api.dto.sale.SaleResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class SaleApi { @@ -22,10 +25,17 @@ public class SaleApi { public List listSales(int page, int size, String query) throws Exception { String path = "/api/v1/sales?page=" + page + "&size=" + size; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from sales endpoint"); + } + return pageResponse.getContent(); } public SaleResponse getSale(Long id) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/ServiceApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/ServiceApi.java index 3ca554f1..66b348dc 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/ServiceApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/ServiceApi.java @@ -3,9 +3,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.common.BulkDeleteRequest; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.service.ServiceRequest; import org.example.petshopdesktop.api.dto.service.ServiceResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class ServiceApi { @@ -23,10 +26,17 @@ public class ServiceApi { public List listServices(String query) throws Exception { String path = "/api/v1/services?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from services endpoint"); + } + return pageResponse.getContent(); } public ServiceResponse createService(ServiceRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/SupplierApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/SupplierApi.java index 9fe5eaad..bcfb8acb 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/SupplierApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/SupplierApi.java @@ -3,9 +3,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; import org.example.petshopdesktop.api.dto.common.BulkDeleteRequest; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.supplier.SupplierRequest; import org.example.petshopdesktop.api.dto.supplier.SupplierResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class SupplierApi { @@ -23,10 +26,17 @@ public class SupplierApi { public List listSuppliers(String query) throws Exception { String path = "/api/v1/suppliers?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from suppliers endpoint"); + } + return pageResponse.getContent(); } public SupplierResponse createSupplier(SupplierRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/api/endpoints/UserApi.java b/src/main/java/org/example/petshopdesktop/api/endpoints/UserApi.java index 54a58c0e..315d53a1 100644 --- a/src/main/java/org/example/petshopdesktop/api/endpoints/UserApi.java +++ b/src/main/java/org/example/petshopdesktop/api/endpoints/UserApi.java @@ -2,9 +2,12 @@ package org.example.petshopdesktop.api.endpoints; import com.fasterxml.jackson.core.type.TypeReference; import org.example.petshopdesktop.api.ApiClient; +import org.example.petshopdesktop.api.dto.common.PageResponse; import org.example.petshopdesktop.api.dto.user.UserRequest; import org.example.petshopdesktop.api.dto.user.UserResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; public class UserApi { @@ -22,10 +25,17 @@ public class UserApi { public List listUsers(String query) throws Exception { String path = "/api/v1/users?page=0&size=1000"; if (query != null && !query.isEmpty()) { - path += "&q=" + query; + path += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); } - String response = apiClient.get(path, String.class); - return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + String response = apiClient.getRawResponse(path); + PageResponse pageResponse = apiClient.getObjectMapper().readValue( + response, + new TypeReference>() {} + ); + if (pageResponse == null) { + throw new IllegalStateException("Null response from users endpoint"); + } + return pageResponse.getContent(); } public UserResponse createUser(UserRequest request) throws Exception { diff --git a/src/main/java/org/example/petshopdesktop/controllers/LoginController.java b/src/main/java/org/example/petshopdesktop/controllers/LoginController.java index 20e34420..c3162df1 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/LoginController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/LoginController.java @@ -54,17 +54,27 @@ public class LoginController { LoginRequest loginRequest = new LoginRequest(username, password); LoginResponse loginResponse = apiClient.post("/api/v1/auth/login", loginRequest, LoginResponse.class); + if (loginResponse == null) { + throw new IllegalStateException("Login response is null"); + } + String token = loginResponse.getToken(); String roleStr = loginResponse.getRole(); + if (token == null || roleStr == null) { + throw new IllegalStateException("Token or role is null"); + } Role role = Role.valueOf(roleStr.toUpperCase()); UserSession.getInstance().login(null, username, role, token); UserInfoResponse userInfo = apiClient.get("/api/v1/auth/me", UserInfoResponse.class); + if (userInfo == null) { + throw new IllegalStateException("User info is null"); + } UserSession.getInstance().login(userInfo.getId(), username, role, token); List stores = DropdownApi.getInstance().getStores(); - if (!stores.isEmpty()) { + if (stores != null && !stores.isEmpty()) { UserSession.getInstance().setStoreId(stores.get(0).getId()); } diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java index ed1fca7c..a1ed25fb 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java @@ -67,8 +67,10 @@ public class AdoptionDialogController { try { List pets = DropdownApi.getInstance().getPets(); Platform.runLater(() -> { - ObservableList petsObs = FXCollections.observableArrayList(pets); - cbPet.setItems(petsObs); + if (pets != null) { + ObservableList petsObs = FXCollections.observableArrayList(pets); + cbPet.setItems(petsObs); + } }); } catch (Exception e) { Platform.runLater(() -> { @@ -85,8 +87,10 @@ public class AdoptionDialogController { try { List customers = DropdownApi.getInstance().getCustomers(); Platform.runLater(() -> { - ObservableList customersObs = FXCollections.observableArrayList(customers); - cbCustomer.setItems(customersObs); + if (customers != null) { + ObservableList customersObs = FXCollections.observableArrayList(customers); + cbCustomer.setItems(customersObs); + } }); } catch (Exception e) { Platform.runLater(() -> { @@ -144,7 +148,11 @@ public class AdoptionDialogController { if (mode.equals("Add")) { AdoptionApi.getInstance().createAdoption(request); } else { - Long adoptionId = Long.parseLong(lblAdoptionId.getText().split(": ")[1]); + String[] parts = lblAdoptionId.getText().split(": "); + if (parts.length < 2) { + throw new IllegalStateException("Invalid adoption ID format"); + } + Long adoptionId = Long.parseLong(parts[1]); AdoptionApi.getInstance().updateAdoption(adoptionId, request); } @@ -197,7 +205,14 @@ public class AdoptionDialogController { } if (adoption.getAdoptionDate() != null && !adoption.getAdoptionDate().isEmpty()) { - dpAdoptionDate.setValue(LocalDate.parse(adoption.getAdoptionDate())); + try { + dpAdoptionDate.setValue(LocalDate.parse(adoption.getAdoptionDate())); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "AdoptionDialogController.displayAdoptionDetails", + e, + "Parsing adoption date"); + } } for (String status : cbAdoptionStatus.getItems()) { diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java index ecefa73c..f0db4368 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java @@ -80,9 +80,15 @@ public class AppointmentDialogController { List pets = DropdownApi.getInstance().getPets(); Platform.runLater(() -> { - cbService.setItems(FXCollections.observableArrayList(services)); - cbCustomer.setItems(FXCollections.observableArrayList(customers)); - cbPet.setItems(FXCollections.observableArrayList(pets)); + if (services != null) { + cbService.setItems(FXCollections.observableArrayList(services)); + } + if (customers != null) { + cbCustomer.setItems(FXCollections.observableArrayList(customers)); + } + if (pets != null) { + cbPet.setItems(FXCollections.observableArrayList(pets)); + } }); } catch (Exception e) { Platform.runLater(() -> { @@ -163,15 +169,29 @@ public class AppointmentDialogController { selectedAppointment = appt; lblAppointmentId.setText("ID: " + appt.getAppointmentId()); - dpAppointmentDate.setValue( - java.time.LocalDate.parse(appt.getAppointmentDate()) - ); + try { + dpAppointmentDate.setValue( + java.time.LocalDate.parse(appt.getAppointmentDate()) + ); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "AppointmentDialogController.displayAppointmentDetails", + e, + "Parsing appointment date"); + } cbAppointmentStatus.setValue(appt.getAppointmentStatus()); - LocalTime time = LocalTime.parse(appt.getAppointmentTime()); - cbHour.setValue(time.getHour()); - cbMinute.setValue(time.getMinute()); + try { + LocalTime time = LocalTime.parse(appt.getAppointmentTime()); + cbHour.setValue(time.getHour()); + cbMinute.setValue(time.getMinute()); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "AppointmentDialogController.displayAppointmentDetails", + e, + "Parsing appointment time"); + } cbService.getItems().forEach(s -> { if (s.getId() == appt.getServiceId()) cbService.setValue(s); diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/InventoryDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/InventoryDialogController.java index fd594c18..3a0b1518 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/InventoryDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/InventoryDialogController.java @@ -70,17 +70,19 @@ public class InventoryDialogController { //Load product list from API into combobox try { List productResponses = ProductApi.getInstance().listProducts(null); - ObservableList products = FXCollections.observableArrayList(); - for (ProductResponse pr : productResponses) { - products.add(new Product( - pr.getId().intValue(), - pr.getProductName(), - pr.getPrice().doubleValue(), - 0, - pr.getDescription() - )); + if (productResponses != null) { + ObservableList products = FXCollections.observableArrayList(); + for (ProductResponse pr : productResponses) { + products.add(new Product( + pr.getId().intValue(), + pr.getProductName(), + pr.getPrice().doubleValue(), + 0, + pr.getDescription() + )); + } + cbProduct.setItems(products); } - cbProduct.setItems(products); } catch (Exception e) { ActivityLogger.getInstance().logException( "InventoryDialogController.initialize", @@ -126,12 +128,22 @@ public class InventoryDialogController { InventoryRequest request = new InventoryRequest(); Product selectedProduct = cbProduct.getSelectionModel().getSelectedItem(); request.setProductId((long) selectedProduct.getProdId()); - request.setStockQuantity(Integer.parseInt(txtQuantity.getText())); + int quantity; + try { + quantity = Integer.parseInt(txtQuantity.getText()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid quantity format"); + } + request.setStockQuantity(quantity); if (mode.equals("Add")) { InventoryApi.getInstance().createInventory(request); } else { - Long inventoryId = Long.parseLong(lblInventoryId.getText().split(": ")[1]); + String[] parts = lblInventoryId.getText().split(": "); + if (parts.length < 2) { + throw new IllegalStateException("Invalid inventory ID format"); + } + Long inventoryId = Long.parseLong(parts[1]); InventoryApi.getInstance().updateInventory(inventoryId, request); } diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/PetDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/PetDialogController.java index d41790dc..1ea93d3e 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/PetDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/PetDialogController.java @@ -107,7 +107,11 @@ public class PetDialogController { if(mode.equals("Add")) { PetApi.getInstance().createPet(request); } else { - Long petId = Long.parseLong(lblPetId.getText().split(": ")[1]); + String[] parts = lblPetId.getText().split(": "); + if (parts.length < 2) { + throw new IllegalStateException("Invalid pet ID format"); + } + Long petId = Long.parseLong(parts[1]); PetApi.getInstance().updatePet(petId, request); } @@ -142,9 +146,18 @@ public class PetDialogController { request.setSpecies(txtPetSpecies.getText()); request.setBreed(txtPetBreed.getText()); request.setPetStatus(cbPetStatus.getValue()); - request.setPrice(new BigDecimal(txtPetPrice.getText())); + try { + request.setPrice(new BigDecimal(txtPetPrice.getText())); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid price format"); + } - int age = Integer.parseInt(txtPetAge.getText()); + int age; + try { + age = Integer.parseInt(txtPetAge.getText()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid age format"); + } LocalDate dateOfBirth = LocalDate.now().minusYears(age); request.setDateOfBirth(dateOfBirth); 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 298478aa..b35cd57e 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductDialogController.java @@ -70,14 +70,16 @@ public class ProductDialogController { //Set up combobox for selecting category try { List categories = DropdownApi.getInstance().getCategories(); - ObservableList categoriesObs = FXCollections.observableArrayList(categories); - cbProdCategory.setItems(categoriesObs); + if (categories != null) { + ObservableList categoriesObs = FXCollections.observableArrayList(categories); + cbProdCategory.setItems(categoriesObs); + } } catch (Exception e) { ActivityLogger.getInstance().logException( "ProductDialogController.initialize", e, "Loading categories for combo box"); - throw new RuntimeException(e); + System.out.println("Error loading categories: " + e.getMessage()); } } @@ -110,14 +112,24 @@ public class ProductDialogController { try { ProductRequest request = new ProductRequest(); request.setProductName(txtProdName.getText()); - request.setPrice(new BigDecimal(txtProdPrice.getText())); + BigDecimal price; + try { + price = new BigDecimal(txtProdPrice.getText()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid price format"); + } + request.setPrice(price); 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]); + String[] parts = lblProdId.getText().split(": "); + if (parts.length < 2) { + throw new IllegalStateException("Invalid product ID format"); + } + Long productId = Long.parseLong(parts[1]); ProductApi.getInstance().updateProduct(productId, request); } diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java index a94a6012..3b67fc54 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java @@ -119,8 +119,12 @@ public class ProductSupplierDialogController { var products = DropdownApi.getInstance().getProducts(); Platform.runLater(() -> { - cbSupplier.setItems(FXCollections.observableArrayList(suppliers)); - cbProduct.setItems(FXCollections.observableArrayList(products)); + if (suppliers != null) { + cbSupplier.setItems(FXCollections.observableArrayList(suppliers)); + } + if (products != null) { + cbProduct.setItems(FXCollections.observableArrayList(products)); + } }); } catch (Exception e) { Platform.runLater(() -> { @@ -204,7 +208,11 @@ public class ProductSupplierDialogController { ProductSupplierRequest request = new ProductSupplierRequest(); request.setSupplierId(cbSupplier.getSelectionModel().getSelectedItem().getId()); request.setProductId(cbProduct.getSelectionModel().getSelectedItem().getId()); - request.setSupplierPrice(new BigDecimal(txtCost.getText())); + try { + request.setSupplierPrice(new BigDecimal(txtCost.getText())); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid cost format"); + } return request; } diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java index 18dab623..b54e3b31 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java @@ -99,7 +99,11 @@ public class SupplierDialogController { if (mode.equals("Add")) { SupplierApi.getInstance().createSupplier(request); } else { - Long supplierId = Long.parseLong(lblSupId.getText().split(": ")[1]); + String[] parts = lblSupId.getText().split(": "); + if (parts.length < 2) { + throw new IllegalStateException("Invalid supplier ID format"); + } + Long supplierId = Long.parseLong(parts[1]); SupplierApi.getInstance().updateSupplier(supplierId, request); }