3

I have created a new annotation to validate my parameters on a controller:

@Constraint(validatedBy = ValueValidator.class)
@Target( { ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidValue {
    String message() default "Invalid value";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

This is my validator:

public class ValueValidator implements ConstraintValidator<ValidValue, String> {
    @Override
    public void initialize(ValidValue constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if (s.contains("hello")) {
            throw new IllegalArgumentException("hello is not valid");
        }
        return true;
    }
}

And this is my controller:

@GetMapping(value = "/extraction-date", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Find  customers by extraction date")
public ResponseEntity<List<Customer>> findAllCustomersByExtractionDate(@RequestParam @ValidValue String value)
{
    System.out.println(value);
    return null;
}

my controller is annotated with:

@RestController
@RequestMapping("api/v1/customers")
@AllArgsConstructor
@Controller
@Validated
@CrossOrigin
@Tag(name = "customer-controller", description = "Controller managing operations related to customers ")

I also have an Advice controller, which I'm intending to use to catch the thrown exception:

@ControllerAdvice()
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * @param ex a Throwable
     * @return a responseEntity with a descriptive message and some other information
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ErrorMessage globalExceptionHandler(Throwable ex) {
        LOG.error(ex.getMessage());
        return getErrorMessage();
    }

    /**
     * @param ex a Exception
     * @return a responseEntity with a descriptive message and some other information
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ErrorMessage globalExceptionHandler(Exception ex) {
        LOG.error(ex.getMessage());
        return getErrorMessage();
    }

    /**
     * @param ex      an InvalidInputException
     * @return a responseEntity with a descriptive message and some other information
     */
    @ExceptionHandler({InvalidInputException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorMessage invalidInputExceptionHandler(Exception ex) {
        LOG.error(ex.getMessage());
        return getErrorMessage(ex, ErrorCode.INVALID_INPUT_ERROR);
    }

    /**
     * @param ex      an ResourceNotFoundException
     * @param request the request from the client
     * @return a responseEntity with a descriptive message and some other information
     */
    @ExceptionHandler({ResourceNotFoundException.class})
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorMessage resourceNotFoundException(Exception ex, WebRequest request) {
        LOG.error(ex.getMessage());
        return getErrorMessage(ex, ErrorCode.RESOURCE_NOT_FOUND);
    }

    /**
     * @param ex thrown exception
     * @param errorCode to be returned to the client in message
     * @return the error message with all attributes
     */
    private ErrorMessage getErrorMessage(Exception ex, ErrorCode errorCode) {
        return new ErrorMessage(
                errorCode.code,
                new Date(),
                ex.getMessage(),
                errorCode.description);
    }

    /**
     * @return the error message with all attributes
     */
    private ErrorMessage getErrorMessage() {
        return new ErrorMessage(
                ErrorCode.INTERNAL_ERROR.code,
                new Date(),
                "Error while proceeding a joinPoint, unhandled exception: see log messages for more details.",
                ErrorCode.INTERNAL_ERROR.description);
    }
} 

This is what I get after calling the method from postman: enter image description here

What I got on the console:

INFO |2021-11-17T08:51:48,898|88D0657C2A8042FDBD32C05E96280791| [http-nio-8080-exec-1] com.obs.dqsc.api.controller.CustomerController - Entered in CustomerController.findAllCustomersByExtractionDate(hello)
hello
INFO |2021-11-17T08:51:48,903|88D0657C2A8042FDBD32C05E96280791| [http-nio-8080-exec-1] com.obs.dqsc.api.controller.CustomerController - Exit from CustomerController.findAllCustomersByExtractionDate(..); Execution time: 2 ms;

The dependencies I have in my pom.xml:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>


    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.5.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

Please could anyone tell me what I am missing?

2
  • exactly that was the problem, I've read in this article reflectoring.io/bean-validation-with-spring-boot that we don't need starter-validator if we have already starter-web included, but on another article I've found the opposite here : yawintutor.com/… so now it's working correctly. thank you! Commented Nov 17, 2021 at 9:16
  • 1
    (probably) it was true in the past, but evolved! ;-) easy fix! +1 Commented Nov 17, 2021 at 9:25

1 Answer 1

8

I was missing the start-validator to make it work, so all what I had to do is to add this dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency> 
Sign up to request clarification or add additional context in comments.

1 Comment

I was missing @Validated annotation, it started working after I added it on the class where I was using My Custom Validator

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.