0

I have written an AbstractCRUDController class and have a getById method as shown below

public abstract class AbstractCRUDController<ENTITY extends BaseEntity, POSTDTO extends BaseDTO, PATCHDTO extends BaseDTO, RESPONSEDTO extends BaseDTO> {
    private AbstractCRUDApi<ENTITY, POSTDTO, PATCHDTO, RESPONSEDTO> restApi;

    private AbstractApiResponseDTOConverter<RESPONSEDTO> apiResponseDTOConverter;

    public static final String SUCCESS = "SUCCESS";

    public AbstractCRUDController(
            AbstractCRUDApi<ENTITY, POSTDTO, PATCHDTO, RESPONSEDTO> restApi,
            AbstractApiResponseDTOConverter<RESPONSEDTO> apiResponseDTOConverter) {
        this.restApi = restApi;
        this.apiResponseDTOConverter = apiResponseDTOConverter;
    }

    @GetMapping("/{id}")
    public ResponseEntity<ApiResponseDTO> getById(
            @Valid
            @PathVariable(name = "id")
            @IsNumberValidatorConstraint String id){
        Long convertedId = Long.parseLong(id);

        RESPONSEDTO filteredResource = this.restApi.findById(convertedId);
        ResponseEntity<ApiResponseDTO> response = this.apiResponseDTOConverter
                .convertToApiResponse(SUCCESS, filteredResource, HttpStatus.OK, null, null);

        return response;
    }
}

This will be extended by ProjectController and other controller implementations so that by default all the controllers will have the GET mapping (as below)

@Validated
@RestController
@RequestMapping("/api/projects")
public class ProjectController extends AbstractCRUDController<Project, ProjectPostDTO, ProjectPatchDTO, ProjectResponseDTO> {
    private ProjectApi projectApi;
    private ProjectApiResponseDTOConverter projectApiResponseDTOConverter;

    @Autowired
    public ProjectController(final ProjectApi projectApi,
                             final ProjectApiResponseDTOConverter projectApiResponseDTOConverter) {
        super(projectApi, projectApiResponseDTOConverter);

        this.projectApi = projectApi;
        this.projectApiResponseDTOConverter = projectApiResponseDTOConverter;
    }
}

When the GET mapping is hit it is working as expected.

enter image description here

But when the id is not a number my custom validator (@IsNumberValidatorConstraint) kicks in and gives the default message(input is not a number as shown below)

enter image description here

But I want the message changed depending on whether I search for a project, a customer or any other entity. For example "Project id is invalid" or "Customer id is invalid".

Is there any way how I can achieve this?

Cheers

Edited

Below is my validator code

import com.theravado.custom.annotation.IsNumberValidatorConstraint;
import org.apache.commons.lang3.math.NumberUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class IsNumberValidator implements ConstraintValidator<IsNumberValidatorConstraint, String> {
    @Override
    public boolean isValid(String number, ConstraintValidatorContext cxt) {
        return NumberUtils.isParsable(number);
    }
}

The annotation is below

@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IsNumberValidator.class)
public @interface IsNumberValidatorConstraint {
    String message() default "input is not a number";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
Shanka Somasiri
  • 581
  • 1
  • 8
  • 30

1 Answers1

0

In your validator, you can add the message on the ConstraintValidatorContext

((ConstraintValidatorContextImpl) context).addMessageParameter("wrongValue", "Project ID is not valid");
grekier
  • 2,322
  • 1
  • 16
  • 23