javamongodbspring-bootuuid

ID format issue as UUID String in Spring Boot with MongoDb


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?


Solution

  • 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)
            }
        }
    
    }