https://kotlinlang.org logo
#spring
Title
# spring
s

Siddhartha Juluru

08/13/2022, 2:23 AM
Does anyone know if it's possible to use JSR-380 validation without being required to have all my class constructor parameters be nullable? Meaning can I do this
@Entity
class Test(@field:NonNull val param: String)
or do I have to do
@Entity
class Test(@field:NonNull val param: String?)
In case anyone is wondering, my current alternative is doing. Source: https://stackoverflow.com/a/55718413
Copy code
@Entity
class Test(
    @field:NonNull
    @JsonProperty("param")
    private var _param: String?,

    @Id
    @GeneratedValue
    var id: Long? = null
) {
    var param: String
        get() = this._param!!
        set(value) {
            this._param = value
        }
}
m

Matthew Gast

08/13/2022, 6:49 PM
It's definitely possible. We use JSR-380 in our Spring Boot API w/ Kotlin & Jackson and it works well. You don't even need the @field:NotNull annotation as if the field is not nullable then it will fail earlier.
Now if you're asking about how well it would work that way with JPA/Hibernate, that I couldn't tell you.
s

Siddhartha Juluru

08/13/2022, 6:58 PM
The only reason I have the annotations is because with them, I can catch all the validation issues by creating a exception handler for MethodArgumentNotValidException instead of handling them one by one in handleHttpMessageNotReadable
Another possible alternative is just creating the models in Java and keeping the rest in Kotlin
^ Just tested this and seems like that just results in a bunch of boilerplate. Honestly might just temporarily switch to Java since this validation stuff is kind of annoying
j

Jacob

08/14/2022, 5:04 AM
Sounds like you need to let them be nullable if you want the exception you're expecting.
Not sure how java is any better than a nullable string
t

thanksforallthefish

08/15/2022, 6:17 AM
yeah, we ended doing something similar to https://kotlinlang.slack.com/archives/C0B8ZTWE4/p1660398058374429?thread_ts=1660357385.215289&cid=C0B8ZTWE4, though we validate at API level (so jackson). the problem is that validation happens on the bean, so values need to be already bound, which means kotlin non null type “triggers” before the validation does. the problem is specific to nullable field and in your case I would consider dropping the validation, but it depends what your application does. in our case, the DB is not an “input” but just a storage, and the only thing allowed to write to the database is the application. so entities and db data is always valid
our flow is
http call -> API level (syntactic validation, like non null, non empty, size, etc) -> domain/logic (business rule validation) -> db (dummy, just read/write)
👌 1
s

Siddhartha Juluru

08/15/2022, 2:09 PM
By API Level Validation, do you mean validating in the handler for the request mapping? Seems like an interesting approach.
m

Matthew Gast

08/15/2022, 7:28 PM
In our case, we use standardized API error messages. Jackson itself will handily throw
MissingKotlinParameterException
for any non-initialized non-null fields in a Kotlin property, so we catch that in a
@ControllerAdvice
exception handler and parse out the property name (which is unfortunately pretty hacky) and send out an appropriate error message. Another downside with this approach is that it will only display one error at a time, so if you have multiple fields which are null that shouldn't be (or any other validation issues), it won't show them all in the error message (as opposed to JSR-380 which can display multiple error messages depending on configuration and implementation).
t

thanksforallthefish

08/15/2022, 7:33 PM
yep, that is true as well. one error at a time is pretty bad experience imo, that is another reason we went for nullable fields in our API representations and then the old
!!
when mapping towards the domain. I am not sure right now how swagger docs generation works with nullable fields annotated with
@NotNull
but I think it generates docs with fields marked as mandatory, so all good there too
192 Views