Skip to content

Commit b6bfd8b

Browse files
authored
Merge pull request #18 from ozgliderpilot/bugfix/lombok-data
Add tests that fail with current entities implementation based on lombok data annotation
2 parents 0e208f2 + 0d535bd commit b6bfd8b

7 files changed

Lines changed: 102 additions & 23 deletions

File tree

memex/src/main/java/com/johnlpage/memex/VehicleInspection/model/Vehicle.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@
55

66
import java.util.List;
77

8-
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.Getter;
10+
import lombok.Setter;
911
import org.springframework.data.annotation.ReadOnlyProperty;
1012

11-
@Data
13+
@Getter
14+
@Setter
15+
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
1216
@JsonIgnoreProperties(ignoreUnknown = true)
1317
@JsonInclude(JsonInclude.Include.NON_NULL)
1418
public class Vehicle {
19+
@EqualsAndHashCode.Include
1520
Long vehicleid;
1621
String make;
1722
String model;

memex/src/main/java/com/johnlpage/memex/VehicleInspection/model/VehicleInspection.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import com.johnlpage.memex.util.DeleteFlag;
88
import com.johnlpage.memex.util.ObjectConverter;
99
import jakarta.validation.constraints.Min;
10-
import lombok.Data;
10+
import lombok.EqualsAndHashCode;
11+
import lombok.Getter;
12+
import lombok.Setter;
1113
import org.springframework.data.annotation.Id;
1214
import org.springframework.data.annotation.Transient;
1315
import org.springframework.data.annotation.Version;
@@ -18,7 +20,7 @@
1820
import java.util.HashMap;
1921
import java.util.Map;
2022

21-
/* Replace @Data with this to make an Immutable model
23+
/* Replace @Getter/@Setter with this to make an Immutable model
2224
* which is a little more efficient but no setters just a builder
2325
* This also impact the controller and fuzzer and JsonLoaderService -
2426
* changes there are commented
@@ -28,12 +30,15 @@
2830
* @Value
2931
*/
3032

31-
@Data
33+
@Getter
34+
@Setter
35+
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
3236
@JsonIgnoreProperties(ignoreUnknown = true)
3337
@JsonInclude(JsonInclude.Include.NON_NULL)
3438
@Document(collection = "vehicleinspection")
3539
public class VehicleInspection {
3640
@Id
41+
@EqualsAndHashCode.Include
3742
Long testid;
3843

3944
@Field("lock_version")

memex/src/main/java/com/johnlpage/memex/generics/service/DocumentHistory.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import java.util.Date;
66
import java.util.Map;
77

8-
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.Getter;
10+
import lombok.Setter;
911
import org.bson.types.ObjectId;
1012
import org.springframework.data.annotation.Id;
1113
import org.springframework.data.mongodb.core.mapping.Document;
1214

13-
/* Replace @Data with this to make an Immutable model
15+
/* Replace @Getter/@Setter with this to make an Immutable model
1416
* which is a little more efficient but no setters just a builder
1517
* This also impacts the controller and PreWriteTrigger and
1618
* JsonLoaderService changes there are commented
@@ -20,12 +22,15 @@
2022
* @Value
2123
*/
2224

23-
@Data
25+
@Getter
26+
@Setter
27+
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
2428
@JsonIgnoreProperties(ignoreUnknown = true)
2529
@JsonInclude(JsonInclude.Include.NON_NULL)
2630
@Document()
2731
public class DocumentHistory {
2832
@Id
33+
@EqualsAndHashCode.Include
2934
ObjectId historyId;
3035
Object recordId;
3136
Date timestamp;

memex/src/main/java/com/johnlpage/memex/generics/service/MongoDbJsonStreamingLoaderService.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
import com.johnlpage.memex.util.UpdateStrategy;
1010
import com.mongodb.bulk.BulkWriteResult;
1111
import jakarta.annotation.Nullable;
12-
import lombok.AllArgsConstructor;
13-
import lombok.Data;
1412
import lombok.RequiredArgsConstructor;
1513
import org.slf4j.Logger;
1614
import org.slf4j.LoggerFactory;
@@ -131,13 +129,11 @@ public JsonStreamingLoadResponse loadFromJsonStream(
131129
}
132130
}
133131

134-
@Data
135-
@AllArgsConstructor
136-
public static class JsonStreamingLoadResponse {
137-
long updates;
138-
long deletes;
139-
long inserts;
140-
boolean success;
141-
String message;
142-
}
132+
public record JsonStreamingLoadResponse(
133+
long updates,
134+
long deletes,
135+
long inserts,
136+
boolean success,
137+
String message
138+
) {}
143139
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.johnlpage.memex.VehicleInspection.model;
2+
3+
import org.junit.jupiter.api.Test;
4+
import java.util.List;
5+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
6+
7+
class VehicleInspectionTest {
8+
9+
@Test
10+
void toString_noStackOverflow_whenVehicleHasInspections() {
11+
VehicleInspection inspection = new VehicleInspection();
12+
inspection.setTestid(1L);
13+
14+
Vehicle vehicle = new Vehicle();
15+
vehicle.setVehicleid(100L);
16+
vehicle.setInspections(List.of(inspection));
17+
18+
inspection.setVehicle(vehicle);
19+
20+
assertDoesNotThrow(() -> inspection.toString());
21+
}
22+
23+
@Test
24+
void equals_noStackOverflow_whenVehicleHasInspections() {
25+
VehicleInspection a = new VehicleInspection();
26+
a.setTestid(1L);
27+
VehicleInspection b = new VehicleInspection();
28+
b.setTestid(1L);
29+
30+
// Separate Vehicle instances so equals() can't short-circuit on reference equality
31+
Vehicle vehicleA = new Vehicle();
32+
vehicleA.setVehicleid(100L);
33+
vehicleA.setInspections(List.of(a));
34+
35+
Vehicle vehicleB = new Vehicle();
36+
vehicleB.setVehicleid(100L);
37+
vehicleB.setInspections(List.of(b));
38+
39+
a.setVehicle(vehicleA);
40+
b.setVehicle(vehicleB);
41+
42+
assertDoesNotThrow(() -> a.equals(b));
43+
}
44+
45+
@Test
46+
void hashCode_noStackOverflow_whenVehicleHasInspections() {
47+
VehicleInspection inspection = new VehicleInspection();
48+
inspection.setTestid(1L);
49+
50+
Vehicle vehicle = new Vehicle();
51+
vehicle.setVehicleid(100L);
52+
vehicle.setInspections(List.of(inspection));
53+
54+
inspection.setVehicle(vehicle);
55+
56+
assertDoesNotThrow(() -> inspection.hashCode());
57+
}
58+
}

memex/templates/model/Model.java.template

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter;
55
import com.fasterxml.jackson.annotation.JsonAnySetter;
66
import com.johnlpage.memex.util.DeleteFlag;
77
import com.johnlpage.memex.util.ObjectConverter;
8-
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.Getter;
10+
import lombok.Setter;
911
import lombok.NoArgsConstructor;
1012
import lombok.AllArgsConstructor;
1113
import org.springframework.data.annotation.Id;
@@ -19,13 +21,16 @@ import java.util.Map;
1921

2022
__idImport__
2123

22-
@Data
24+
@Getter
25+
@Setter
26+
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
2327
@NoArgsConstructor
2428
@AllArgsConstructor
2529
@Document(collection = "__collectionName__")
2630
public class __className__ {
2731

2832
@Id
33+
@EqualsAndHashCode.Include
2934
private __idType__ __idFieldName__;
3035

3136
@Field("lock_version")

memex/templates/scripts/generate-models-from-json.groovy

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,9 @@ processClass = { Map classes, String className, Map fields, boolean isRoot, Stri
457457
isRoot : isRoot,
458458
fields : [],
459459
imports : new HashSet([
460-
'lombok.Data',
460+
'lombok.Getter',
461+
'lombok.Setter',
462+
'lombok.EqualsAndHashCode',
461463
'org.springframework.data.mongodb.core.mapping.Field',
462464
'com.fasterxml.jackson.annotation.JsonAnySetter',
463465
'com.fasterxml.jackson.annotation.JsonAnyGetter',
@@ -556,7 +558,9 @@ def generateClassContent = { Map classInfo, String pkgName, String collectionNam
556558
sb.append(" */\n")
557559

558560
// Annotations
559-
sb.append("@Data\n")
561+
sb.append("@Getter\n");
562+
sb.append("@Setter\n");
563+
sb.append("@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n");
560564
if (classInfo.isRoot) {
561565
sb.append("@Document(collection = \"${collectionName}\")\n")
562566
}
@@ -567,6 +571,7 @@ def generateClassContent = { Map classInfo, String pkgName, String collectionNam
567571
if (classInfo.isRoot) {
568572
// Add ID field first
569573
sb.append(" @Id\n")
574+
sb.append(" @EqualsAndHashCode.Include\n")
570575
sb.append(" private String ${classInfo.idFieldName};\n\n")
571576

572577
// Add version field

0 commit comments

Comments
 (0)