【问题标题】:Bean Validation on Jax-RS Resource stops working while using CDI on Apache TomEE 8.0.10在 Apache TomEE 8.0.10 上使用 CDI 时,Jax-RS 资源上的 Bean 验证停止工作
【发布时间】:2023-01-26 23:42:51
【问题描述】:

我在让 bean 验证与以下仅由这三个 java 文件和 pom.xml 组成的最小化项目一起工作时遇到了麻烦。我正在使用 Apache TomEE 8.0.10。

登录消息.java

package org.example;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.validation.constraints.NotBlank;

@Getter
@Setter
@ToString
public class LoginMessage {

    @NotBlank
    private String username;

    @NotBlank
    private String password;
}

会话服务.java

package org.example;

import lombok.extern.java.Log;

import javax.enterprise.context.RequestScoped;

@Log
@RequestScoped
public class SessionService {

    public void login(final LoginMessage loginMessage) {
        log.info(loginMessage.toString());
    }
}

会话控制器.java

package org.example;

import lombok.extern.java.Log;

import javax.inject.Inject;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;

@Log
@Path("/session")
public class SessionController {

    @Inject
    private SessionService sessionService;

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public void postLoginMessage(@Valid final LoginMessage loginMessage) {
        sessionService.login(loginMessage);
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <packaging>war</packaging>

    <groupId>org.example</groupId>
    <artifactId>beanval</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>8.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>
</project>

如果您发布一个空的 JSON 对象,它会忽略 SessionController#postLoginMessage() 中的 @Valid 注释,并通过 SessionService#login() 方法直接输出包含 LoginMessage 对象的 toString() 内容的日志消息。

POST http://localhost:8080/beanval-1.0-SNAPSHOT/session
Content-Type: application/json

{
}
13-Mar-2022 01:30:39.700 INFORMATION [http-nio-8080-exec-6] SessionService.login LoginMessage(username=null, password=null)

如果您从 SessionService 中删除或注释掉 @RequestScoped 注释并在 TomEE 重新启动后发布空的 JSON 对象,则 bean 验证工作并记录:

13-Mar-2022 01:52:51.594 WARNUNG [http-nio-8080-exec-6] org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.toResponse Value (null) of SessionController.postLoginMessage.arg0.password: must not be blank
13-Mar-2022 01:52:51.595 WARNUNG [http-nio-8080-exec-6] org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.toResponse Value (null) of SessionController.postLoginMessage.arg0.username: must not be blank

我想在 JAX-RS 资源中结合使用 CDI 和 Bean-Validation。 我究竟做错了什么?

提前致谢。

【问题讨论】:

  • 我是为了以简洁明了的方式提出问题来补充。
  • 如果你使用@ApplicationScoped 而不是@RequestScoped 会发生什么?
  • @JonathanS.Fisher 谢谢。 @ApplicationScoped@Stateless也是一样的
  • 我现在也用 @SessionScoped 尝试了它,结果相同。

标签: jax-rs cdi bean-validation apache-tomee


【解决方案1】:

这似乎是 OpenWebBeans 或 TomEE 中的错误。所以发生的事情是第一个 bean 的实际实例由 JAX-RS 管理,第二个 bean 由 CDI 容器管理。在第二种情况下,需要有某种调用 Bean Validation 框架的拦截器。

我会在邮件列表上开始讨论并在 JIRA 上打开一个错误。如果您可以创建一个重现该问题的示例项目,它可以极大地帮助开发人员解决问题。

作为解决方法,您可以@Inject private Validator validator,如果返回任何约束违规,throw new ConstraintViolationException(constraintViolations);

【讨论】:

  • 完全同意 - 非常感谢通过 dev@tomee.apache.org 发送的示例代码 + 邮件。
  • 此外,我们在内部对此进行了测试,看起来它只影响 JSON 负载,这很有趣
  • @JonathanS.Fisher 我无法重现这个。我现在已经尝试使用application/xml并将有效负载更改为&lt;loginMessage/&gt;。这导致与 json 相同的行为。
  • @rzo1 上面的代码是一个完整的工作示例,请随时将其提交到上述电子邮件地址。
  • miracles-whip 由你来提交 :) 开源依赖于像你这样的社区成员像你上面那样提交经过深思熟虑的例子。告诉你什么,你可以跳过邮件列表,但在这里记录一个错误并附上你的代码! issues.apache.org/jira/projects/TOMEE/issues/…
【解决方案2】:

毕竟想出某种解决方案,我将停止在控制器层使用 bean 验证。它在服务层工作,所以我可以继续在我的网络应用程序上工作。

解决方案是在 SessionService#login() 方法中使用 @Valid 注释,并将其从 SessionController#postLoginMessage() 方法中删除。

如果它确实是 TomEE 中的一个错误,也可以使用另一个应用程序服务器,直到它被修复。

【讨论】:

    猜你喜欢
    • 2012-07-01
    • 2018-12-11
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多