I am a newbie in Spring-boot and was learning to validate constraints, here the #NotBlank, #NonNull doesn't seem to work. What I want is to provide bad request for the null value given. Am I missing something here?
The snippet of model class has been given below:
Person.java
public class Person {
private final UUID id;
#NotBlank
private final String name;
public Person(#JsonProperty("id") UUID id,
#JsonProperty("name") String name){
this.id = id;
this.name = name;
}
And the controller class is given below:
PersonController.java
#PostMapping
public void addPerson(#Valid #NonNull #RequestBody Person person) {
personService.addPerson(person);
}
pom.xml
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
Turns out the problem was in the pom.xml file.
About the validation part: The Validation Starter dependency is no longer included in the web starter dependencies (source: [check][1])
Select it when creating the Spring Boot config or just add at the pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
[1]: import javax.validation.constraints.NotEmpty; not working)
Related
I checked in several different ways to check where is bug but I still do not know the answer.
That is my RestController
#RestController
public class CustomerController {
#PostMapping(value = "/customer")
public ResponseEntity<CustomerResponse> addCustomer(#RequestBody #Valid Customer custRequest) throws Exception {
ModelMapper modelMapper = new ModelMapper();
CustomerDto customerDto = modelMapper.map(custRequest, CustomerDto.class);
CustomerDto addCust = customer.addCustomer(customerDto);
CustomerResponse custResponse = modelMapper.map(addCust, CustomerResponse.class);
return new ResponseEntity<CustomerResponse>(custResponse, HttpStatus.CREATED);
}
}
That is my Model
#Entity
#Table(name = "customers")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String idCustomer;
private String email;
#OneToMany(mappedBy = "customer",cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private List<Choice> choices;
// Getter and setter and constructor
}
maven dependencies
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
response of postman
How can i resolve this problem to post a new customer .
#Valid lets the framework check against the parameter on the method invocation and, if the validation fails, an HTTP 400 Bad Request status is thrown. You are having a complex type and that type requires a validation too. Here's a link:
https://medium.com/javarevisited/are-you-using-valid-and-validated-annotations-wrong-b4a35ac1bca4
Try removing the #Valid just to see the difference and the above article gives you an example implementation.
Also, using an Entity as a Request object is a highly discouraged paradigm. You are encouraged to make a DTO object specific to your request as a start. There are situations where you have to inherit, but this question's scope is not that.
The validation of Customer seems to fail.
I would
look at the logs to error details
think about having a separate class for the request object. You do not really want to mix database related and request related concerns.
Working with MongoDB, I decided username should be unique. Okay, I use #Indexed(unique = true) (application runs fine), but #Indexed(unique = true) isn't working. I can still add 2 users with the same username.
Source (Spring Data: Unique field in MongoDB document) tells me to put spring.data.mongodb.auto-index-creation=true in my application.properties. (also tried putting it in application.yml, gave same error)
Later I also realized the #Size annotation from the jakarta.validation-api doesn't work.
User model:
import org.bson.types.Binary;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import javax.persistence.Id;
import javax.validation.constraints.Size;
import java.util.List;
#Document(collection = "users")
public class User {
#Id
private String id;
private Binary profilePicture;
private String bio;
#Size(max = 20)
#Indexed(unique = true)
private String username;
private String password;
private List<Integer> kweets;
private List<User> followers;
private List<User> following;
}
Repository (is just standard):
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UserRepository extends MongoRepository<User, String> {
}
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
</dependencies>
Id's do get auto-generated though, which means #Id does work.
Where could the problem lay, at first I thought it was just #Indexed, but turns out #Size doesn't work either.
It's fixed. Idk what it was, I stashed all the changes I made and it still works. I didn't change anything and it suddenly worked...
I have a RestController containing an HTTP endpoint to create a new user.
#RestController
public class UserController {
#PostMapping("/user")
public CompletableFuture<ResponseEntity<UserResponse>> createUser(
#Valid #RequestBody UserRequest userRequest) {
return CompletableFuture.completedFuture(
ResponseEntity.status(HttpStatus.ACCEPTED).body(userService.createUser(userRequest)));
}
}
My UserRequest model is as follows:
#Getter
#Setter
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(NON_NULL)
#NoArgsConstructor
public class UserRequest {
// #NotNull
#NotEmpty private String name;
}
Now, every time I invoke the POST /user endpoint with a valid payload (e.g., { "name": "John" }), I get the following error:
HV000030: No validator could be found for constraint 'javax.validation.constraints.NotEmpty' validating type 'java.lang.String'. Check configuration for 'name'"
In other words, the exception is thrown regardless of whether the "name" property was empty or not.
However, when I use the #NotNull constraint instead, the exception is only thrown in the absence of the name property or { "name": null }, as expected.
Am I misusing the #NotEmpty constraint?
Maven dependencies (in pom.xml) -
<!-- Java bean validation API - Spec -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- Hibernate validator - Bean validation API Implementation -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.11.Final</version>
</dependency>
<!-- Verify validation annotations usage at compile time -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.0.11.Final</version>
</dependency>
In the user request model-
import javax.validation.constraints.NotEmpty;
#NotEmpty(message = "Name cannot be empty")
private String name;
For validation String's variable, you should use #NotBlank this constraint check null and blank value for String's variable(blank for example "" or " ") or #NotNull if you want to check the only nullable value
#NotEmpty for Collection's type check.
Check this for more information: https://www.baeldung.com/java-bean-validation-not-null-empty-blank
I created a project using spring boot 2.1.4.RELEASE with the following dependencies:
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
I have the following entity and repository:
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "last_name")
private String lastName;
#Column(name = "age")
private Integer age;
#Column(name = "createdAt")
#Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
...
}
PersonRepository.java
#Repository
public interface PersonRepository extends CrudRepository<Person, Integer> {
}
The following is my Application class:
#SpringBootApplication
public class SpringDataApplication {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(SpringDataApplication.class, args);
PersonRepository personRepository = context.getBean(PersonRepository.class);
Person p1 = new Person("Juan", "Camaney", 55);
Person p2 = new Person("Arturo", "Lopez", 33);
Person p3 = new Person("Pancho", "Coscorin", 22);
personRepository.save(p1);
personRepository.save(p2);
personRepository.save(p3);
Iterator<Person> people = personRepository.findAll().iterator();
while (people.hasNext()) {
Person temp = people.next();
System.out.println(temp);
}
}
}
If i execute my application i get the following error:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.devs4j.spring.data.repositories.PersonRepository' available
The solution of it is add the following configuration class:
#Configuration
#EnableJpaRepositories("com.devs4j.spring.data.repositories")
public class JpaConfiguration {
}
But I get the error :
EnableJpaRepositories cannot be resolved to a type
If i downgrade to 2.0.5.RELEASE everything works fine.
I'm confused because when i check the following spring documentation https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/reference/html/ I see that it is still using #EnableJpaRepositories("com.acme.repositories")
Am i doing something wrong ?
In your configuration.java, have you added the import:
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
I try to produce xml-format data from spring boot restcontroller. Below is User model codes first.
#Entity
#Table(name="BlogUser")
#XmlRootElement
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="USER_ID", nullable = false, unique = true)
private Long id;
#Column(unique=true, nullable=false)
#Length(min=2, max=30)
#NotEmpty
private String username;
#Column(nullable=false)
#Length(min=5)
#NotEmpty
private String password;
#Column
#Email
#NotEmpty
private String email;
#Column
#NotEmpty
private String fullname;
#Column
private UserRole role;
}
And Below codes are RestConstroller.java
#RestController
#RequestMapping(value="/rest/user")
#SessionAttributes("user")
public class UserRestController {
#Autowired
private UserService userService;
#GetMapping(value="getAllUser", produces=MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<List<User>> getAllPost() {
List<User> users = this.userService.findAll();
if(users == null || users.isEmpty())
return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
}
}
Json format data are successfully returned. But xml-format values are not generated. It throws the following exception.
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
I add the a few dependencies into pom.xml like below,
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
But still throws the same exception. I can not understand what I miss to solve this issue.
Set the consumes attribute in your #GetMapping annotation.
#GetMapping(value = "getAllUser", produces = MediaType.APPLICATION_XML_VALUE, consumes = MediaType.APPLICATION_XML_VALUE)
(Posted on behalf of the question author).
I modify the method like below:
#GetMapping(value="getAllUser", produces = { "application/xml", "text/xml" }, consumes = MediaType.ALL_VALUE)
public ResponseEntity<List<User>> getAllPost() {
..
It work perfectly. It return xml-type values.