I created an example of Spring Boot with MongoDb. I have a problem in getting an entity by id with validation as it throws "must be a valid UUID
".
Here is the entity shown below
@Getter
@Setter
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "airport-collection")
public class AirportEntity extends BaseEntity {
@Id
@Indexed(unique = true)
@Field(name = "_id")
private String id = UUID.randomUUID().toString();
@Field(name = "AIRPORT_NAME")
private String name;
@Field(name = "CITY_NAME")
private String cityName;
}
When I call getAirportById(@PathVariable @Valid @UUID final String id)
from Controller like localhost:8080/api/v1/airports/6781972fa25a3e577395c444 , I got this issue shown below
{
"time": "2025-01-11T00:55:27.5670908",
"httpStatus": "BAD_REQUEST",
"header": "VALIDATION ERROR",
"message": "Constraint violation",
"isSuccess": false,
"subErrors": [
{
"message": "must be a valid UUID",
"field": "id",
"value": "6781972fa25a3e577395c444",
"type": "String"
}
]
}
Here is the value stored in the collection
_id : ObjectId(6781972fa25a3e577395c444)
AIRPORT_NAME : String
CITY_NAME : String
_class : Entity class
How can I fix the issue?
Here is the solution shown below.
1 ) Revise id of the entity as private String id
@Getter
@Setter
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "airport-collection")
public class AirportEntity extends BaseEntity {
@Id
@Indexed(unique = true)
private String id;
@Field(name = "AIRPORT_NAME")
private String name;
@Field(name = "CITY_NAME")
private String cityName;
}
2 ) Define setEntityIdIfNeeded method in BaseEntityListener extending from AbstractMongoEventListener to define UUID string format as id
@Component
public class BaseEntityListener extends AbstractMongoEventListener<BaseEntity> {
/**
* Sets auditing fields before converting the entity to a MongoDB document.
*
* @param event the event triggered before entity conversion.
*/
@Override
public void onBeforeConvert(BeforeConvertEvent<BaseEntity> event) {
BaseEntity entity = event.getSource();
// Set ID for entities that have it
setEntityIdIfNeeded(entity);
...
}
/**
* Checks if the entity has an 'id' field and sets it to a new UUID if it is null or empty.
*
* @param entity the entity to check and modify
*/
private void setEntityIdIfNeeded(BaseEntity entity) {
try {
// Use reflection to check if the entity has an 'id' field
Field idField = entity.getClass().getDeclaredField("id");
idField.setAccessible(true); // Make the field accessible
// If the field is null or empty, set it to a new UUID
Object idValue = idField.get(entity);
if (idValue == null || idValue.toString().isEmpty()) {
idField.set(entity, UUID.randomUUID().toString());
}
} catch (NoSuchFieldException | IllegalAccessException e) {
// If no 'id' field is found, or it can't be accessed, ignore (entity may not have an 'id' field)
}
}
}