I am writing simple CRUD with Kotlin + Spring Boot + Hibernate and came up with the issue:
I have a field in User
class called age
and type Int
import javax.persistence.*
import javax.validation.constraints.NotBlank
import javax.validation.constraints.Size
@Entity
@Table(name = "users")
data class User(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long,
@NotBlank
@Column(unique = true)
@Size(min = 1, max = 100)
val username: String,
@NotBlank
@Size(max = 50)
val firstName: String,
@Size(max = 50)
val lastName: String?,
@Size(min = 1, max = 100)
val age: Int
)
Then I have post request which creates a user
@PostMapping
fun post(@RequestBody user: User): User {
log.debug("POST: {}", user)
return userRepository.save(user)
}
The problem is that when I miss age
field in JSON it doesn't respond with 400 error, but defaults to 0
instead.
How do I make this field required ?
I think that a bigger problem is that you are using the same class (your entity) for multiple purposes. This makes this class very unflexible since you can't adapt it to the needs of your REST endpoint and to the needs of Hibernate as well.
What I'd do instead is having a boundary between the two (something like Clean Architecture would suggest to do):
data class UserDTO(val id: Long?,
var username: String?,
var firstName: String?,
var lastName: String?,
var age: Int?) {
fun toUser() = User(
id = id ?: signalError(),
username = username ?: signalError(),
firstName = firstName ?: signalError(),
lastName = lastName ?: signalError(),
age = age ?: signalError())
private fun signalError() : Nothing = throw IllegalArgumentException(
"Missing parameter in UserDTO.")
}
I solved the issue thanks to this post , also thanks to @Adam Arold for showing best practices.
I created new UserDTO
class:
import ai.leavingstone.flywayspringdemo.domain.User
import javax.validation.constraints.*
data class UserDTO(
private val id: Long = -1,
@field:NotBlank
@field:Size(min = 1, max = 100)
private val username: String,
@field:NotBlank
@field:Size(max = 50)
private val firstName: String,
@field:Size(max = 50)
private val lastName: String?,
@field:NotNull
private val age: Int?
) {
fun toUser(): User = User(
id,
username,
firstName,
lastName,
age!!
)
}
Before none of data validation annotations worked, after adding @field
prefix it's working fine. @NotNull
on Int
is also working and default value for id
field as well.
You should use @Valid @RequestBody user: User
for the method parameter so spring is going to validate the given body. This should be done by default but just in case write it down and it´s better for new workers etc.
Also @ Size
annotation does not support primitives or numeric vars. It just verifies a length of String
, Array
, Map
, List
... So just annotate it with @Min
and @Max
. So the default Value of 0 would not be valid anymore.
Also for a nullable object to validate you can use Integer
instead of Int
so you can check just @NotNull
if you want negatives or 0 be valid, too without getting default value 0.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.