• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

abdulkader138 / personal-expense-tracker / #84

12 Jan 2026 12:04AM UTC coverage: 98.739% (-1.2%) from 99.925%
#84

push

abdulkader138
code refactoring

12 of 26 new or added lines in 4 files covered. (46.15%)

2 existing lines in 1 file now uncovered.

1331 of 1348 relevant lines covered (98.74%)

0.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.08
/src/main/java/com/mycompany/pet/controller/CategoryController.java
1
package com.mycompany.pet.controller;
2

3
import java.sql.SQLException;
4
import java.util.List;
5
import java.util.function.Consumer;
6

7
import com.mycompany.pet.model.Category;
8
import com.mycompany.pet.service.CategoryService;
9

10
/**
11
 * Controller for Category operations.
12
 * Separates UI concerns from business logic.
13
 * 
14
 * This controller handles:
15
 * - Category CRUD operations
16
 * - Error handling and user feedback
17
 * - Thread-safe database operations
18
 */
19
public class CategoryController {
20
    private final CategoryService categoryService;
21
    
22
    public CategoryController(CategoryService categoryService) {
1✔
23
        this.categoryService = categoryService;
1✔
24
    }
1✔
25
    
26
    /**
27
     * Load all categories.
28
     * 
29
     * @param onSuccess Callback with list of categories
30
     * @param onError Callback with error message
31
     */
32
    public void loadCategories(Consumer<List<Category>> onSuccess, Consumer<String> onError) {
33
        Thread thread = new Thread(() -> {
1✔
34
            try {
35
                List<Category> categories = categoryService.getAllCategories();
1✔
36
                javax.swing.SwingUtilities.invokeLater(() -> onSuccess.accept(categories));
1✔
37
            } catch (SQLException e) {
1✔
38
                String errorMsg = "Error loading categories: " + e.getMessage();
1✔
39
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
1✔
NEW
40
            } catch (RuntimeException e) {
×
NEW
41
                String errorMsg = "Error loading categories: " + e.getMessage();
×
NEW
42
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
×
43
            }
1✔
44
        });
1✔
45
        thread.setDaemon(true); // Make daemon thread to avoid blocking JVM shutdown
1✔
46
        thread.start();
1✔
47
    }
1✔
48
    
49
    /**
50
     * Create a new category.
51
     * 
52
     * @param name Category name
53
     * @param onSuccess Callback with created category
54
     * @param onError Callback with error message
55
     */
56
    public void createCategory(String name, Consumer<Category> onSuccess, Consumer<String> onError) {
57
        if (name == null || name.trim().isEmpty()) {
1✔
58
            javax.swing.SwingUtilities.invokeLater(() -> 
1✔
59
                onError.accept("Category name cannot be empty."));
1✔
60
            return;
1✔
61
        }
62
        
63
        Thread thread = new Thread(() -> {
1✔
64
            try {
65
                Category category = categoryService.createCategory(name.trim());
1✔
66
                javax.swing.SwingUtilities.invokeLater(() -> onSuccess.accept(category));
1✔
67
            } catch (SQLException e) {
1✔
68
                String errorMsg = "Error adding category: " + e.getMessage();
1✔
69
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
1✔
NEW
70
            } catch (IllegalArgumentException e) {
×
NEW
71
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(e.getMessage()));
×
NEW
72
            } catch (RuntimeException e) {
×
NEW
73
                String errorMsg = "Error adding category: " + e.getMessage();
×
NEW
74
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
×
75
            }
1✔
76
        });
1✔
77
        thread.setDaemon(true);
1✔
78
        thread.start();
1✔
79
    }
1✔
80
    
81
    /**
82
     * Update an existing category.
83
     * 
84
     * @param categoryId Category ID
85
     * @param name New category name
86
     * @param onSuccess Callback with updated category
87
     * @param onError Callback with error message
88
     */
89
    public void updateCategory(Integer categoryId, String name, 
90
                               Consumer<Category> onSuccess, Consumer<String> onError) {
91
        if (name == null || name.trim().isEmpty()) {
1✔
92
            javax.swing.SwingUtilities.invokeLater(() -> 
1✔
93
                onError.accept("Category name cannot be empty."));
1✔
94
            return;
1✔
95
        }
96
        
97
        Thread thread = new Thread(() -> {
1✔
98
            try {
99
                Category category = categoryService.updateCategory(categoryId, name.trim());
1✔
100
                javax.swing.SwingUtilities.invokeLater(() -> onSuccess.accept(category));
1✔
101
            } catch (SQLException e) {
1✔
102
                String errorMsg = "Error updating category: " + e.getMessage();
1✔
103
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
1✔
104
            } catch (IllegalArgumentException e) {
1✔
105
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(e.getMessage()));
1✔
NEW
106
            } catch (RuntimeException e) {
×
NEW
107
                String errorMsg = "Error updating category: " + e.getMessage();
×
NEW
108
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
×
109
            }
1✔
110
        });
1✔
111
        thread.setDaemon(true);
1✔
112
        thread.start();
1✔
113
    }
1✔
114
    
115
    /**
116
     * Delete a category.
117
     * 
118
     * @param categoryId Category ID
119
     * @param onSuccess Callback when deletion succeeds
120
     * @param onError Callback with error message
121
     */
122
    public void deleteCategory(Integer categoryId, Runnable onSuccess, Consumer<String> onError) {
123
        Thread thread = new Thread(() -> {
1✔
124
            try {
125
                categoryService.deleteCategory(categoryId);
1✔
126
                javax.swing.SwingUtilities.invokeLater(onSuccess);
1✔
127
            } catch (SQLException e) {
1✔
128
                String errorMsg = "Error deleting category: " + e.getMessage();
1✔
129
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
1✔
130
            } catch (IllegalArgumentException e) {
1✔
131
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(e.getMessage()));
1✔
NEW
132
            } catch (RuntimeException e) {
×
NEW
133
                String errorMsg = "Error deleting category: " + e.getMessage();
×
NEW
134
                javax.swing.SwingUtilities.invokeLater(() -> onError.accept(errorMsg));
×
135
            }
1✔
136
        });
1✔
137
        thread.setDaemon(true);
1✔
138
        thread.start();
1✔
139
    }
1✔
140
    
141
    /**
142
     * Get a category by ID.
143
     * 
144
     * @param categoryId Category ID
145
     * @return Category or null if not found
146
     * @throws SQLException if database error occurs
147
     */
148
    public Category getCategory(Integer categoryId) throws SQLException {
149
        return categoryService.getCategory(categoryId);
1✔
150
    }
151
}
152

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc