Skip to content

Commit 5e03eaa

Browse files
authored
fix: entity bugs fixed (#12)
- using mappers properly - entity bugs fixed: lombok `@Data` annotation is risky with JPA - input validations done via jakarka - exceptions added - using `BigDecimal` for money instead of `Double` --------- Signed-off-by: Rajdeep Roy Chowdhury <rrajdeeproychowdhury@gmail.com>
1 parent 523a611 commit 5e03eaa

26 files changed

Lines changed: 226 additions & 255 deletions

build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,15 @@ dependencies {
4444
implementation(libs.gson)
4545
implementation(libs.spring.boot.starter.freemarker)
4646
implementation(libs.openhtml)
47+
implementation(libs.spring.boot.starter.validation)
4748

4849
compileOnly(libs.lombok)
4950
annotationProcessor(libs.lombok)
5051

5152
implementation(libs.mapstruct)
5253
annotationProcessor(libs.mapstruct.processor)
5354

54-
annotationProcessor("org.projectlombok:lombok-mapstruct-binding:0.2.0")
55+
annotationProcessor(libs.lombok.mapstruct.binding)
5556

5657
implementation(libs.spring.boot.starter.actuator)
5758
implementation(libs.springdoc.openapi.ui)

gradle/libs.versions.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ jaxb = "2.4.0-b180830.0359"
55
postgres = "42.7.8"
66
gson = "2.10"
77
lombok = "1.18.30" # put actual version you use
8-
mapstruct = "1.5.3.Final"
8+
lombokmapstruct = "0.2.0"
9+
mapstruct = "1.6.3"
910
springdoc = "1.6.14"
1011
jedis = "4.4.2"
1112
jackson = "2.15.0"
@@ -23,12 +24,14 @@ spring-boot-starter-data-redis = { module = "org.springframework.boot:spring-boo
2324
spring-boot-starter-cache = { module = "org.springframework.boot:spring-boot-starter-cache", version = "2.4.3" }
2425
spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test" }
2526
spring-boot-starter-freemarker = { module = "org.springframework.boot:spring-boot-starter-freemarker" }
27+
spring-boot-starter-validation = { module = "org.springframework.boot:spring-boot-starter-validation" }
2628

2729
jjwt = { module = "io.jsonwebtoken:jjwt", version.ref = "jjwt" }
2830
jaxb-api = { module = "javax.xml.bind:jaxb-api", version.ref = "jaxb" }
2931
postgres-connector = { module = "org.postgresql:postgresql", version.ref = "postgres" }
3032
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
3133
lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" }
34+
lombok-mapstruct-binding = { module = "org.projectlombok:lombok-mapstruct-binding", version.ref = "lombokmapstruct" }
3235

3336
mapstruct = { module = "org.mapstruct:mapstruct", version.ref = "mapstruct" }
3437
mapstruct-processor = { module = "org.mapstruct:mapstruct-processor", version.ref = "mapstruct" }

src/main/java/com/razdeep/konsignapi/controller/AuthenticationController.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.razdeep.konsignapi.service.RefreshTokenService;
88
import com.razdeep.konsignapi.token.TokenPair;
99
import jakarta.servlet.http.HttpServletResponse;
10+
import jakarta.validation.Valid;
1011
import org.springframework.http.HttpHeaders;
1112
import org.springframework.http.HttpStatus;
1213
import org.springframework.http.ResponseCookie;
@@ -29,7 +30,7 @@ public AuthenticationController(
2930

3031
@PostMapping("/login")
3132
public ResponseEntity<KonsignApiResponse> login(
32-
@RequestBody AuthenticationRequest authenticationRequest, HttpServletResponse response) {
33+
@Valid @RequestBody AuthenticationRequest authenticationRequest, HttpServletResponse response) {
3334

3435
TokenPair tokenPair = authenticationService.login(authenticationRequest);
3536

@@ -42,8 +43,7 @@ public ResponseEntity<KonsignApiResponse> login(
4243

4344
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
4445

45-
AuthenticationResponse authenticationResponse = new AuthenticationResponse();
46-
authenticationResponse.setAccessToken(tokenPair.accessToken());
46+
AuthenticationResponse authenticationResponse = new AuthenticationResponse(tokenPair.accessToken());
4747

4848
return ResponseEntity.ok(KonsignApiResponse.builder()
4949
.success(true)
@@ -64,7 +64,7 @@ public ResponseEntity<KonsignApiResponse> refresh(
6464
}
6565

6666
@PostMapping(value = "/signup")
67-
public ResponseEntity<KonsignApiResponse> signup(@RequestBody UserRegistration userRegistration)
67+
public ResponseEntity<KonsignApiResponse> signup(@Valid @RequestBody UserRegistration userRegistration)
6868
throws UsernameAlreadyExists {
6969
authenticationService.register(userRegistration);
7070
KonsignApiResponse konsignApiResponse = KonsignApiResponse.builder()

src/main/java/com/razdeep/konsignapi/controller/BillController.java

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.razdeep.konsignapi.model.KonsignApiResponse;
66
import com.razdeep.konsignapi.service.BillService;
77
import io.micrometer.core.annotation.Timed;
8+
import jakarta.validation.Valid;
89
import org.slf4j.Logger;
910
import org.slf4j.LoggerFactory;
1011
import org.springframework.http.HttpStatus;
@@ -27,34 +28,24 @@ public BillController(BillService billService) {
2728

2829
@Timed
2930
@PostMapping
30-
public ResponseEntity<KonsignApiResponse> addBillEntry(@RequestBody Bill bill) {
31-
ResponseEntity<KonsignApiResponse> response;
32-
KonsignApiResponse konsignApiResponse = new KonsignApiResponse();
31+
public ResponseEntity<KonsignApiResponse> addBillEntry(@Valid @RequestBody Bill bill) {
3332

34-
if (bill.anyFieldEmpty()) {
35-
konsignApiResponse.setMessage("Saving bill failed because all fields are not properly filled");
36-
response = new ResponseEntity<>(konsignApiResponse, HttpStatus.NOT_ACCEPTABLE);
37-
} else if (billService.enterBill(bill)) {
38-
konsignApiResponse.setMessage("Successfully saved bill");
39-
response = new ResponseEntity<>(konsignApiResponse, HttpStatus.OK);
40-
} else {
41-
konsignApiResponse.setMessage("Saving bill failed");
42-
response = new ResponseEntity<>(konsignApiResponse, HttpStatus.NOT_ACCEPTABLE);
43-
}
44-
return response;
33+
billService.addBill(bill);
34+
KonsignApiResponse konsignApiResponse = KonsignApiResponse.builder()
35+
.message("Successfully saved bill")
36+
.success(true)
37+
.build();
38+
39+
return ResponseEntity.ok(konsignApiResponse);
4540
}
4641

4742
@Timed
4843
@GetMapping("/{billNo}")
4944
public ResponseEntity<KonsignApiResponse> getBill(@PathVariable String billNo) {
5045
final var bill = billService.getBill(billNo);
51-
KonsignApiResponse konsignApiResponse = new KonsignApiResponse();
52-
if (bill == null) {
53-
konsignApiResponse.setMessage("Bill not found");
54-
return new ResponseEntity<>(konsignApiResponse, HttpStatus.NOT_FOUND);
55-
}
56-
konsignApiResponse.setData(bill);
57-
return new ResponseEntity<>(konsignApiResponse, HttpStatus.OK);
46+
KonsignApiResponse konsignApiResponse =
47+
KonsignApiResponse.builder().success(true).data(bill).build();
48+
return ResponseEntity.ok(konsignApiResponse);
5849
}
5950

6051
@Timed
@@ -66,13 +57,8 @@ public ResponseEntity<KonsignApiResponse> getAllBills(
6657
final var bills = billService.getAllBills(offset, pageSize);
6758
stopWatch.stop();
6859
LOG.info("billEntryService.getAllBills() took {} ms", stopWatch.getLastTaskTimeMillis());
69-
KonsignApiResponse konsignApiResponse = new KonsignApiResponse();
70-
if (bills == null) {
71-
konsignApiResponse.setMessage("Bill not found");
72-
return new ResponseEntity<>(konsignApiResponse, HttpStatus.NOT_FOUND);
73-
}
74-
konsignApiResponse.setData(bills);
75-
return new ResponseEntity<>(konsignApiResponse, HttpStatus.OK);
60+
return new ResponseEntity<>(
61+
KonsignApiResponse.builder().success(true).data(bills).build(), HttpStatus.OK);
7662
}
7763

7864
@Timed

src/main/java/com/razdeep/konsignapi/entity/BaseTimestamp.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
import jakarta.persistence.Column;
44
import jakarta.persistence.MappedSuperclass;
55
import java.time.LocalDateTime;
6-
import lombok.Data;
6+
import lombok.Getter;
7+
import lombok.Setter;
78
import org.hibernate.annotations.CreationTimestamp;
89
import org.hibernate.annotations.UpdateTimestamp;
910

1011
@MappedSuperclass
11-
@Data
12+
@Getter
13+
@Setter
1214
public class BaseTimestamp {
1315

1416
@CreationTimestamp

src/main/java/com/razdeep/konsignapi/entity/BillEntity.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.razdeep.konsignapi.entity;
22

33
import jakarta.persistence.*;
4+
import java.math.BigDecimal;
45
import java.time.LocalDate;
56
import java.util.List;
67
import lombok.*;
@@ -31,7 +32,9 @@ public class BillEntity extends BaseTimestamp {
3132
private TransportEntity transportEntity;
3233

3334
private LocalDate lrDate;
34-
private Double billAmount;
35+
36+
@Column(nullable = false, precision = 15, scale = 2)
37+
private BigDecimal billAmount;
3538

3639
@OneToMany(cascade = CascadeType.ALL, mappedBy = "billEntry")
3740
private List<LrPmEntity> lrPmEntityList;

src/main/java/com/razdeep/konsignapi/entity/CollectionVoucherItemEntity.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.razdeep.konsignapi.entity;
22

33
import jakarta.persistence.*;
4+
import java.math.BigDecimal;
45
import java.time.LocalDate;
56
import lombok.*;
67

@@ -25,7 +26,8 @@ public class CollectionVoucherItemEntity extends BaseTimestamp {
2526
@JoinColumn(name = "bill_bill_no")
2627
BillEntity bill;
2728

28-
Double amountCollected;
29+
@Column(nullable = false, precision = 15, scale = 2)
30+
BigDecimal amountCollected;
2931

3032
String bank;
3133

src/main/java/com/razdeep/konsignapi/entity/RefreshTokenEntity.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
import jakarta.persistence.*;
44
import java.time.Instant;
55
import java.util.UUID;
6-
import lombok.AllArgsConstructor;
7-
import lombok.Builder;
8-
import lombok.Data;
9-
import lombok.NoArgsConstructor;
6+
import lombok.*;
107

118
@Entity
129
@Table(name = "refresh_tokens")
13-
@Data
10+
@Getter
11+
@Setter
1412
@AllArgsConstructor
1513
@NoArgsConstructor
1614
@Builder

src/main/java/com/razdeep/konsignapi/exception/GlobalExceptionHandler.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.razdeep.konsignapi.exception;
22

33
import com.razdeep.konsignapi.model.KonsignApiResponse;
4+
import java.util.ArrayList;
5+
import java.util.List;
46
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
68
import org.springframework.http.HttpStatus;
79
import org.springframework.http.ResponseEntity;
810
import org.springframework.security.authentication.BadCredentialsException;
11+
import org.springframework.web.bind.MethodArgumentNotValidException;
912
import org.springframework.web.bind.annotation.ExceptionHandler;
1013
import org.springframework.web.bind.annotation.RestControllerAdvice;
1114

@@ -56,4 +59,36 @@ public ResponseEntity<KonsignApiResponse> handleGenericException(Exception ex) {
5659
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
5760
.body(new KonsignApiResponse(false, "An unexpected error occurred", null));
5861
}
62+
63+
@ExceptionHandler(MethodArgumentNotValidException.class)
64+
public ResponseEntity<KonsignApiResponse> handleValidationErrors(MethodArgumentNotValidException ex) {
65+
66+
List<String> missingFields = new ArrayList<>();
67+
68+
ex.getBindingResult().getFieldErrors().forEach(error -> missingFields.add(error.getField()));
69+
70+
String message = String.join(",", missingFields) + " not properly passed";
71+
72+
return ResponseEntity.badRequest()
73+
.body(KonsignApiResponse.builder()
74+
.success(false)
75+
.message(message)
76+
.build());
77+
}
78+
79+
@ExceptionHandler(ResourceNotFoundException.class)
80+
public ResponseEntity<KonsignApiResponse> handleValidationErrors(ResourceNotFoundException ex) {
81+
82+
LOG.info("Resource not found", ex);
83+
84+
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new KonsignApiResponse(false, ex.getMessage(), null));
85+
}
86+
87+
@ExceptionHandler(SaveResourceException.class)
88+
public ResponseEntity<KonsignApiResponse> handleValidationErrors(SaveResourceException ex) {
89+
90+
LOG.info("Resource could not be saved", ex);
91+
92+
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new KonsignApiResponse(false, ex.getMessage(), null));
93+
}
5994
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.razdeep.konsignapi.exception;
2+
3+
public class ResourceNotFoundException extends RuntimeException {
4+
public ResourceNotFoundException(String message) {
5+
super(message);
6+
}
7+
}

0 commit comments

Comments
 (0)