【问题标题】:How do I correctly validate a REST request in Quarkus using Kotlin?如何使用 Kotlin 在 Quarkus 中正确验证 REST 请求?
【发布时间】:2021-08-15 15:37:32
【问题描述】:

我目前正在使用 Kotlin 在 Quarkus 中创建一个应用程序。我正在尝试使用 RestEasy、Panache 和 Hibernate 创建一个简单的用户端点。我现在面临的挑战是异常处理没有正确完成。当请求无效时,我想向用户显示正确且易于理解的消息。

这是我用于 createUser POST 请求的 UserResource:

@POST
    @Transactional
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    fun createUser(@Valid user: User) : CreateUserResponse =
        try {
            userRepository.persist(user)
            CreateUserSuccess(user)
        } catch (e: Exception) {
            CreateUserFailure(e)
        }

这是我的用户实体:

@Entity
data class User (
    @Id
    @GeneratedValue(generator = "UUID")
    var id: UUID? = UUID.randomUUID(),

    @NotBlank
    var fullName: String,

    @Email
    @NotBlank(message = "email may not be blank")
    var email: String,

    @CreationTimestamp
    var createdAt: LocalDateTime? = null,

    @UpdateTimestamp
    var updatedAt: LocalDateTime? = null,
)

为了完整起见,这是我的 UserRepository:

@ApplicationScoped
class UserRepository : PanacheRepository<User>

当我确定请求有效时,创建用户确实有效。但我还想确保在请求无效时能很好地处理无效请求。这是我在点击 createUser 端点时得到的响应:

com.fasterxml.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of
`com.fortuneapp.backend.application.domain.core.models.entities.User`, problem: Parameter specified as non-null is null:
method com.fortuneapp.backend.application.domain.core.models.entities.User.&lt;init&gt;, parameter email
at [Source: (io.quarkus.vertx.http.runtime.VertxInputStream); line: 3, column: 1]

我在这里错过了什么?

【问题讨论】:

    标签: kotlin error-handling quarkus quarkus-panache quarkus-rest-client


    【解决方案1】:

    您在属性的可空性方面遇到了问题,因为您可以看到甚至很难定义 var 属性,其中一些属性不可为空 ? 所以因为您要反序列化 json 消息,输入休息服务,Jackson 无法创建模型类 user 的新实例,因为某些必填字段不存在。

    这类似于您尝试创建一个新对象但未在构造函数中提供所需的参数。

    这里有一些使用 kotlin、Jax-RS 和 Hibernate-Panache 的建议https://quarkus.io/guides/kotlin

    您尝试归档的内容完全有可能,但如果您想使用实体作为请求主体,则必须使所有字段可为空,否则底层 Json 序列化程序将无法创建模型的新实例以通过@Valid 验证并生成约束违规报告。


    这里有一些选择。

    1. 您可以创建一个所有属性都可以为空的 Data 类,这样您就可以确保能够检查所有 javax 验证注释,因为请求能够被反序列化。然后将此对象映射到您的模型实体类。您可以将此类视为 DTO,因为最终您正在通过层边界移动数据并将服务合同与实体模型实现中的服务合同解耦,这往往很方便。
    2. 尽管使用 javax.validation 约束注释非常方便,但您可以注入验证器并检索约束违规,并以比默认报告更易读的方式返回包含约束违规的自定义数据类,默认报告在 resteasy 的响应式版本中,quarkus 不支持。

    如果您有更多疑问,我可以提供一个示例。

    【讨论】:

    • 嗨@karelss,感谢您的全面回答。我将实体类中的所有字段都更改为可为空。最终的诀窍是将注释从 NotBlank 更改为 field:NotBlank。再次感谢!
    • @RicardodeVries 你很高兴将答案标记为接受然后如果你不介意
    【解决方案2】:

    将您的字段设置为可空,初始化它们并将@field:放在注释​​之前,它将起作用。

    @Entity
    data class User (
        @Id
        @GeneratedValue(generator = "UUID")
        var id: UUID? = UUID.randomUUID(),
    
        @field:NotBlank
        var fullName: String = null,
    
        @field:Email
        @NotBlank(message = "email may not be blank")
        var email: String = null,
    
        ...
    

    【讨论】:

      猜你喜欢
      • 2021-08-11
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 2016-07-01
      • 1970-01-01
      • 2018-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多