62

Given below is my main controller from which I am calling the getPDFDetails method.

@RequestMapping(value=PATH_PRINT_CONTRACTS, method=RequestMethod.POST)
    public ResponseEntity<?> printContracts(@RequestBody final UpdatePrintContracts updatePrintContracts) throws Exception {
    
        System.out.println("contracts value is "+ updatePrintContracts);
        
        Integer cancellationReasons = service.getPDFDetails(updatePrintContracts);
        
        System.out.println("success!");
        
        return ResponseEntity.ok(cancellationReasons);
    }   

Below is the UpdatePrintContracts class where I have defined all the variables with validation annotations and corresponding getter/setter methods.

public class UpdatePrintContracts {
    
    @Valid
    @NotBlank
    @Pattern(regexp = "\\p{Alnum}{1,30}")
    String isReprint;
    
    @Valid
    @NotBlank
    Integer dealerId;
    
    @Valid
    @NotBlank
    @Pattern(regexp = "\\p{Alnum}{1,30}")
    String includeSignatureCoordinates;
    
    @Valid
    @NotBlank
    java.util.List<Integer> contractNumbers;

    public String getIsReprint() {
        return isReprint;
    }

    public void setIsReprint(String isReprint) {
        this.isReprint = isReprint;
    }

    public Integer getDealerId() {
        return dealerId;
    }

    public void setDealerId(Integer dealerId) {
        this.dealerId = dealerId;
    }

    public String getIncludeSignatureCoordinates() {
        return includeSignatureCoordinates;
    }

    public void setIncludeSignatureCoordinates(String includeSignatureCoordinates) {
        this.includeSignatureCoordinates = includeSignatureCoordinates;
    }

    public java.util.List<Integer> getContractNumbers() {
        return contractNumbers;
    }

    public void setContractNumbers(java.util.List<Integer> contractNumbers) {
        this.contractNumbers = contractNumbers;
    }
    
}

I am trying to run the application as a Spring Boot app by right clicking on the project (Run As) and passing blank values for variables isReprint and includeSignatureCoordinates through Soap UI. However the validation doesn't seem to work and is not throwing any validation error in Soap UI. What am I missing? Any help is appreciated!

mtotowamkwe
  • 2,407
  • 2
  • 12
  • 19
Poonkodi Sivapragasam
  • 1,127
  • 4
  • 18
  • 27
  • 2
    `@NotBlank` is for text only, not integer. Try to start from the simplest, with only one field for validation like `@NotBlank String foo;` if that works, move on to other more complicated ones like `@Pattern` – Tiina Feb 05 '18 at 02:29
  • In my case I forgot to add @Valid tag in Controller – Rishabh Ryber Nov 12 '21 at 03:17

16 Answers16

125

If you are facing this problem in latest version of spring boot (2.3.0) make sure to add the following dependency:

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

Observation: In earlier version of Spring Boot (1.4.7), javax.validation used to work out of the box. But, after upgrading to latest version, annotations broke. Adding the following dependency alone doesn't work:

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>

Because this provides JSR Specification but not the implementation. You can also use hibernate-validator instead of spring-boot-starter-validation.

Deb
  • 5,163
  • 7
  • 30
  • 45
37

For Anyone who is getting this issue with 2.0.1.Final:

In all SpringBoot versions above 2.2, Validations starter is not a part of web starter anymore

Check Notes here

So, all you have to do is add this dependency in your build.gradle/pom file

GRADLE:

implementation 'org.springframework.boot:spring-boot-starter-validation'

MAVEN

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Thanny
  • 564
  • 5
  • 9
  • I am using `web-starter-2.6.5` apparently no proper validation of `@NotNull`, `@NotEmpty`, and `@NotBlank` there but there is `@NonNull` and `Validated` from `org.springframework.lang`. I was confused a while and verified `@NonNull` and `Validated` are NOT the proper validation to use. Thanks for the answer it helped. – seedme Apr 09 '22 at 07:20
22

I faced the same error.

I had to use the below 2 dependencies alone:

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

And use @Validated annotation(import org.springframework.validation.annotation.Validated) on rest controller level and @Valid annotation at method argument level(import javax.validation.Valid)

If there are any other extra dependencies like javax.validation.validation-api, org.hibernate.hibernate-validator, etc then the validations stopped working for me. So make sure that you remove these dependencies from pom.xml

firstpostcommenter
  • 2,328
  • 4
  • 30
  • 59
  • 1
    Works. Docs don't mention this at all.Like we are just supposed to know these things. – Ojonugwa Jude Ochalifu Dec 31 '21 at 08:19
  • This comment saved me from the debugging hell that I was going through only because I had the `javax.validation.validation-api` and the `org.hibernate.hibernate-validator` as dependencies. By doing the other steps (having the `spring-boot-starter-validation`, the @Validated and @Valid annotations) everything magically worked! Thanks a lot! :D – Lavinia May 13 '22 at 19:44
  • Same problem here, I tried everything, but it only worked after removing the org.hibernate.hibernate-validator from the classpath – George Barbosa Jan 31 '23 at 03:49
19

First you dont need to have @Valid annotation for those class variables in UpdatePrintContracts . You can delete them.

To trigger validation of a @Controller input, simply annotate the input argument as @Valid or @Validated:

@RequestMapping(value=PATH_PRINT_CONTRACTS, method=RequestMethod.POST)
public ResponseEntity<?> printContracts(@Valid @RequestBody  final UpdatePrintContracts updatePrintContracts) throws Exception {

Refer here for full understanding of validating models in spring boot.

And If you want to check that a string contains only specific characters, you must add anchors (^ for beginning of the string, $ for end of the string) to be sure that your pattern matches all the string.Curly brackets are only to write a quantity,

@Pattern(regexp = "^[\\p{Alnum}]{1,32}$")

Lastly i assume you have following jars in your classpath,

.validation-api.jar (contains the abstract API and the annotation scanner)

.hibernate-validator.jar (contains the concrete implementation)

surya
  • 2,581
  • 3
  • 22
  • 34
  • 1
    try not sending isReprint /includeSignatureCoordinates , and see if you get error.Note that not sending and sending blank are 2 different thing, i hope you know what i mean – surya Feb 05 '18 at 02:18
  • Wouldn't a @validated notation above class declaration achieve the same end? – Nate T Apr 27 '21 at 11:32
10

I was using This dependency of validation in spring boot and didn't work ,

<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>

I replaced it with spring-boot-starter-validation and it worked .

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot- 
starter-validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.4.0</version>
Arjun Gautam
  • 321
  • 2
  • 5
8

this is for anyone here who still has the same issue after following the steps mentioned above. I had to restart my IDE (IntelliJ) for the changes to take effect.

CodeLearner
  • 115
  • 2
  • 7
8

Make sure to use @Valid annotation before @RequestBody

For newer versions of spring boot ensure all validation annotation are picked from jakarta.validation.* package and not javax.validation.*. As the annotations are named same in both.

Adarsh R Jayan
  • 159
  • 2
  • 8
  • 1
    I'm using spring boot 3 and hibernate-validator 8.0.0.Final and importing `jakarta.validation.*` instead of `javax.validation.*` annotations is what solved my problem. – luizfzs Jan 29 '23 at 12:33
  • @Adarsh R Jayan perfect answer this is the only solution that is working remember to add `@Validated` in the Controller and also use jakarta import for `@Valid` in the controller – Emmanuel Njorodongo Mar 14 '23 at 08:33
5

My problem solved by this. When we use classes inside classes that also need validations so @Valid needs to be annotated to all in that case. Link for more details

tensor
  • 733
  • 1
  • 13
  • 22
2

Step-1: Add these two dependency in the pom.xml file

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>

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

Step-2: Create a Custom Exception class like this

package com.bjit.salon.auth.service.exceptions;


import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.stream.Collectors;

@ControllerAdvice
public class AnynameApplicationException {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseEntity<List<String>> processUnmergeException(final 
MethodArgumentNotValidException ex) {

        List<String> list = ex.getBindingResult().getAllErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.toList());

        return new ResponseEntity<>(list, HttpStatus.BAD_REQUEST);
    }
}

Step-3: Add @Valid annotation to the method arguments like this way

public ResponseEntity<?> registerAccount(@Valid @RequestBody UserRegisterDto 
      registerDto) {
       
    // rest of the codes
}
Jewel
  • 47
  • 2
  • 7
2

If you are using spring version > 3

and using Kotlin you should add @field:Annotation

ex:

@field:NotEmpty
@field:NotNull
@field:NotBlank(message = "Email is required")
@field:Email(message = "Please provide a valid email")
val email: String,
@field:NotEmpty
@field:NotNull
@field:NotBlank(message = "Password is required")
val password: String,
1

You have to add this dependency in pom.xml

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

Note: SNAPSHOT, M1, M2, M3, and M4 releases typically WORK IN PROGRESS. The Spring team is still working on them, Recommend NOT using them.

Fazal Haroon
  • 845
  • 2
  • 10
  • 20
1

Add this dependency to your pom.xml file and @NotBlank, @NotNull, @Valid, etc. should work fine.

<dependency>
            <groupId>jakarta.validation</groupId>
            <artifactId>jakarta.validation-api</artifactId>
            <version>2.0.2</version>
</dependency>
1

For anyone like me using spring boot 3.X.

After the jackarta update you have to include extra config in order for the request body validation to work. (The field validation was working just fine even without extra config)

At the end all I needed was

@Configuration
public class ValidationConfiguration {

    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }
}

and implementation 'org.springframework.boot:spring-boot-starter-validation'

it is recommended to use the spring boot maven/gradle plugin so there are no version discrepencies

Borislav Stoilov
  • 3,247
  • 2
  • 21
  • 46
0

Same problem with entities in my Kotlin Spring boot 3.x application.
Solved by adding spring-boot-starter-validation dependency and adding anotation @field:NotBlank (or @field:NotNull, @field:NotEmpty) on fields.

salerokada
  • 334
  • 3
  • 7
0

I had same problem For me adding:

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

under the spring-boot-starter-web dependency solved problem. To be sure you should generate dependency directly with Validation form start spring io. It's worth mentioning that order of dependencies in pom file is crucial

Adrian M
  • 9
  • 4
  • While it is true that dependencies order is fundamental, what was your issue? Shading? Wrong version? – dcolazin Aug 29 '23 at 20:04
-1

You can use @NotEmpty will check for both blank and null values. Add @Valid to your RestContoller class methods