Skip to content

Commit df35bdf

Browse files
committed
Change the business logic exception to status exceptions.
1 parent d45e655 commit df35bdf

File tree

7 files changed

+61
-31
lines changed

7 files changed

+61
-31
lines changed

core/src/main/java/com/jongsoft/finance/core/exception/StatusException.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,42 @@
33
public class StatusException extends RuntimeException {
44

55
private final int statusCode;
6+
private final String localizationMessage;
67

7-
private StatusException(int statusCode, String message) {
8+
private StatusException(int statusCode, String message, String localizationMessage) {
89
super(message);
910
this.statusCode = statusCode;
11+
this.localizationMessage = localizationMessage;
1012
}
1113

1214
public int getStatusCode() {
1315
return statusCode;
1416
}
1517

18+
public String getLocalizationMessage() {
19+
return localizationMessage;
20+
}
21+
1622
public static StatusException notFound(String message) {
17-
return new StatusException(404, message);
23+
return new StatusException(404, message, null);
1824
}
1925

2026
public static StatusException badRequest(String message) {
21-
return new StatusException(400, message);
27+
return new StatusException(400, message, null);
28+
}
29+
public static StatusException badRequest(String message, String localizationMessage) {
30+
return new StatusException(400, message, localizationMessage);
2231
}
2332

2433
public static StatusException notAuthorized(String message) {
25-
return new StatusException(401, message);
34+
return new StatusException(401, message, null);
2635
}
2736

2837
public static StatusException internalError(String message) {
29-
return new StatusException(500, message);
38+
return new StatusException(500, message, null);
39+
}
40+
public static StatusException internalError(String message, String localizationMessage) {
41+
return new StatusException(500, message, localizationMessage);
3042
}
3143

3244
}

domain/src/main/java/com/jongsoft/finance/domain/transaction/ScheduledTransaction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ public ScheduledTransaction(String name, Schedule schedule, Account source, Acco
5454
@BusinessMethod
5555
public void limit(LocalDate start, LocalDate end) {
5656
if (start.isAfter(end)) {
57-
throw new IllegalArgumentException("Start of scheduled transaction cannot be after end date.");
57+
throw StatusException.badRequest(
58+
"Start of scheduled transaction cannot be after end date.",
59+
"validation.transaction.schedule.end.before.start");
5860
}
5961

6062
var hasChanged = Control.Equal(this.start, start)

domain/src/main/java/com/jongsoft/finance/domain/user/Budget.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ public Expense(long id, String name, double amount) {
5959
@BusinessMethod
6060
public void updateExpense(double expectedExpense) {
6161
if (computeExpenses() + expectedExpense > expectedIncome) {
62-
throw StatusException.badRequest("Expected expenses exceeds the expected income.");
62+
throw StatusException.badRequest(
63+
"Expected expenses exceeds the expected income.",
64+
"validation.budget.expense.exceeds.income");
6365
}
6466

6567
lowerBound = expectedExpense - .01;
@@ -92,7 +94,9 @@ public double computeBudget() {
9294

9395
Budget(LocalDate start, double expectedIncome) {
9496
if (expectedIncome < 1) {
95-
throw StatusException.internalError("Expected income cannot be less than 1.");
97+
throw StatusException.badRequest(
98+
"Expected income cannot be less than 1.",
99+
"validation.budget.income.too.low");
96100
}
97101

98102
this.start = start;
@@ -131,11 +135,15 @@ public Budget indexBudget(LocalDate perDate, double expectedIncome) {
131135
@BusinessMethod
132136
public void createExpense(String name, double lowerBound, double upperBound) {
133137
if (end != null) {
134-
throw StatusException.badRequest("Cannot add expense to an already closed budget period.");
138+
throw StatusException.badRequest(
139+
"Cannot add expense to an already closed budget period.",
140+
"validation.budget.expense.add.budget.closed");
135141
}
136142

137143
if (computeExpenses() + upperBound > expectedIncome) {
138-
throw StatusException.badRequest("Expected expenses exceeds the expected income.");
144+
throw StatusException.badRequest(
145+
"Expected expenses exceeds the expected income.",
146+
"validation.budget.expense.exceeds.income");
139147
}
140148

141149
expenses = expenses.append(new Expense(name, lowerBound, upperBound));
@@ -151,7 +159,9 @@ void activate() {
151159

152160
void close(LocalDate endDate) {
153161
if (this.end != null) {
154-
throw StatusException.badRequest("Already closed budget cannot be closed again.");
162+
throw StatusException.badRequest(
163+
"Already closed budget cannot be closed again.",
164+
"validation.budget.already.closed");
155165
}
156166

157167
this.end = endDate;

domain/src/main/java/com/jongsoft/finance/domain/user/UserAccount.java

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.jongsoft.finance.annotation.Aggregate;
44
import com.jongsoft.finance.annotation.BusinessMethod;
55
import com.jongsoft.finance.core.AggregateBase;
6+
import com.jongsoft.finance.core.exception.StatusException;
67
import com.jongsoft.finance.domain.account.Account;
78
import com.jongsoft.finance.domain.importer.BatchImportConfig;
89
import com.jongsoft.finance.domain.transaction.Tag;
@@ -126,8 +127,8 @@ public void disableMultiFactorAuthentication() {
126127
*/
127128
@BusinessMethod
128129
public Account createAccount(String name, String currency, String type) {
129-
if (!fullUser()) {
130-
throw new IllegalStateException("User cannot create accounts, incorrect privileges.");
130+
if (notFullUser()) {
131+
throw StatusException.notAuthorized("User cannot create accounts, incorrect privileges.");
131132
}
132133

133134
return new Account(this, name, currency, type);
@@ -141,17 +142,17 @@ public Account createAccount(String name, String currency, String type) {
141142
*/
142143
@BusinessMethod
143144
public Category createCategory(String label) {
144-
if (!fullUser()) {
145-
throw new IllegalStateException("User cannot create categories, incorrect privileges.");
145+
if (notFullUser()) {
146+
throw StatusException.notAuthorized("User cannot create categories, incorrect privileges.");
146147
}
147148

148149
return new Category(this, label);
149150
}
150151

151152
@BusinessMethod
152153
public Tag createTag(String label) {
153-
if (!fullUser()) {
154-
throw new IllegalStateException("User cannot create tags, incorrect privileges.");
154+
if (notFullUser()) {
155+
throw StatusException.notAuthorized("User cannot create tags, incorrect privileges.");
155156
}
156157

157158
EventBus.getBus().send(new CreateTagCommand(label));
@@ -167,8 +168,8 @@ public Tag createTag(String label) {
167168
*/
168169
@BusinessMethod
169170
public TransactionRule createRule(String name, boolean restrictive) {
170-
if (!fullUser()) {
171-
throw new IllegalStateException("User cannot create rules, incorrect privileges.");
171+
if (notFullUser()) {
172+
throw StatusException.notAuthorized("User cannot create rules, incorrect privileges.");
172173
}
173174

174175
return new TransactionRule(this, name, restrictive);
@@ -182,8 +183,8 @@ public TransactionRule createRule(String name, boolean restrictive) {
182183
*/
183184
@BusinessMethod
184185
public BatchImportConfig createImportConfiguration(String name, String fileCode) {
185-
if (!fullUser()) {
186-
throw new IllegalStateException("User cannot create import configuration, incorrect privileges.");
186+
if (notFullUser()) {
187+
throw StatusException.notAuthorized("User cannot create import configuration, incorrect privileges.");
187188
}
188189

189190
return new BatchImportConfig(this, name, fileCode);
@@ -198,18 +199,18 @@ public BatchImportConfig createImportConfiguration(String name, String fileCode)
198199
*/
199200
@BusinessMethod
200201
public Budget createBudget(LocalDate start, double expectedIncome) {
201-
if (!fullUser()) {
202-
throw new IllegalStateException("User cannot create budgets, incorrect privileges.");
202+
if (notFullUser()) {
203+
throw StatusException.notAuthorized("User cannot create budgets, incorrect privileges.");
203204
}
204205

205206
var budget = new Budget(start, expectedIncome);
206207
budget.activate();
207208
return budget;
208209
}
209210

210-
public boolean fullUser() {
211+
public boolean notFullUser() {
211212
return roles.stream()
212-
.anyMatch(r -> Objects.equals(r.getName(), "accountant") || Objects.equals(r.getName(), "admin"));
213+
.noneMatch(r -> Objects.equals(r.getName(), "accountant") || Objects.equals(r.getName(), "admin"));
213214
}
214215

215216
}

domain/src/test/java/com/jongsoft/finance/domain/transaction/ScheduledTransactionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void limit() {
4545

4646
@Test
4747
void limit_endBeforeStart() {
48-
var exception = Assertions.assertThrows(IllegalArgumentException.class, () ->
48+
var exception = Assertions.assertThrows(StatusException.class, () ->
4949
scheduledTransaction.limit(LocalDate.of(2022, 4, 5), LocalDate.of(2019, 1, 1)));
5050

5151
assertThat(exception.getMessage()).isEqualTo("Start of scheduled transaction cannot be after end date.");

domain/src/test/java/com/jongsoft/finance/domain/user/UserAccountTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.jongsoft.finance.domain.user;
22

3+
import com.jongsoft.finance.core.exception.StatusException;
34
import com.jongsoft.finance.domain.account.Account;
45
import com.jongsoft.finance.domain.importer.BatchImportConfig;
56
import com.jongsoft.finance.domain.transaction.TransactionRule;
@@ -62,7 +63,7 @@ void createAccount() {
6263

6364
@Test
6465
void createAccount_NotAllowed() {
65-
IllegalStateException thrown = assertThrows(IllegalStateException.class,
66+
var thrown = assertThrows(StatusException.class,
6667
() -> readOnlyAccount.createAccount("Demo account", "EUR", "checking"));
6768

6869
Mockito.verifyNoInteractions(applicationEventPublisher);
@@ -83,7 +84,7 @@ void createTag() {
8384

8485
@Test
8586
void createTag_NotAllowed() {
86-
IllegalStateException thrown = assertThrows(IllegalStateException.class,
87+
var thrown = assertThrows(StatusException.class,
8788
() -> readOnlyAccount.createTag("Tag 1"));
8889

8990
Mockito.verify(applicationEventPublisher, Mockito.never()).publishEvent(Mockito.any());
@@ -109,7 +110,7 @@ void createCategory() {
109110

110111
@Test
111112
void createCategory_NotAllowed() {
112-
IllegalStateException thrown = assertThrows(IllegalStateException.class,
113+
var thrown = assertThrows(StatusException.class,
113114
() -> readOnlyAccount.createCategory("demo-cat"));
114115

115116
assertThat(thrown.getMessage()).isEqualTo("User cannot create categories, incorrect privileges.");
@@ -126,15 +127,15 @@ void createBatchConfiguration() {
126127

127128
@Test
128129
void createBatchConfiguration_NotAllowed() {
129-
IllegalStateException thrown = assertThrows(IllegalStateException.class,
130+
var thrown = assertThrows(StatusException.class,
130131
() -> readOnlyAccount.createImportConfiguration("test-config", "file-code-sample"));
131132

132133
assertThat(thrown.getMessage()).isEqualTo("User cannot create import configuration, incorrect privileges.");
133134
}
134135

135136
@Test
136137
void createBudget_NotAllowed() {
137-
IllegalStateException thrown = assertThrows(IllegalStateException.class,
138+
var thrown = assertThrows(StatusException.class,
138139
() -> readOnlyAccount.createBudget(LocalDate.of(2019, 1, 1), 2500));
139140

140141
assertThat(thrown.getMessage()).isEqualTo("User cannot create budgets, incorrect privileges.");

fintrack-api/src/main/java/com/jongsoft/finance/filter/StatusExceptionHandler.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public HttpResponse<JsonError> handle(HttpRequest request, StatusException excep
3131
var error = new JsonError(exception.getMessage());
3232
error.link(Link.SELF, Link.of(request.getUri()));
3333

34+
if (exception.getLocalizationMessage() != null) {
35+
error.link(Link.HELP, exception.getLocalizationMessage());
36+
}
37+
3438
return HttpResponse
3539
.status(HttpStatus.valueOf(exception.getStatusCode()))
3640
.body(error);

0 commit comments

Comments
 (0)