当Web方法参数被注释时,JAX-RS Jersey客户端获得400响应

jFr*_*tic 3 jax-rs jersey jersey-client jersey-2.0

这是我的Web服务方法:

@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@POST
@Path("login")
public Response login(@NotNull @Valid Credentials credentials) {
// do login
}
Run Code Online (Sandbox Code Playgroud)

这是客户端代码的片段:

WebTarget loginTarget = baseTarget
        .path("base")
        .path("login");

Credentials credentials = new Credentials(username, password);

Response resp = loginOperation
        .request()
        .post(
            Entity.entity(credentials, MediaType.APPLICATION_JSON_TYPE)
        );
Run Code Online (Sandbox Code Playgroud)

当我发帖时,它没有到达登录方法.服务器返回400错误,空体.

当我@NotNull @Valid从凭证参数中删除注释时,它可以工作.

我注意到Entity#entity方法有一个重载版本,它接受Annotation[]第三个参数.然后我遇到了Jersey文档的这一部分.所以我按照教程中的建议继续创建了一个注释工厂:

public static class ValidFactory extends AnnotationLiteral<Valid> implements Valid {
    public static ValidFactory get() {
        return new ValidFactory();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将客户端代码更改为:

.post(
    Entity.entity(credentials, MediaType.APPLICATION_JSON_TYPE,
        new Annotation[] {
            AuthenticationResource.NotNullFactory.get(), 
            AuthenticationResource.ValidFactory.get()
        }
    )
)
Run Code Online (Sandbox Code Playgroud)

不幸的是导致了同样的错误.谷歌搜索没有产生任何结果,我没有太多时间挖掘泽西岛的源代码.那么,也许知道解决方案的人会分享它,好吗?

UPDATE

只是为了添加@peeskillet的回复.我使用自定义ExceptionMapper:

@Provider
public class ValidationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

    @Override
    public Response toResponse(ConstraintViolationException exception) {
      // customize response
    }

}
Run Code Online (Sandbox Code Playgroud)

因此,在我的情况下,我不必设置ServerProperties.BV_SEND_ERROR_IN_RESPONSE属性,而是必须在服务器配置中注册映射器:

GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI)
        new ResourceConfig() {
            {
                register(ValidationExceptionMapper.class)
            }
        }
);
Run Code Online (Sandbox Code Playgroud)

Pau*_*tha 9

听起来你只需要配置Jersey以使用ServerProperties.BV_SEND_ERROR_IN_RESPONSE 发送错误消息:

public static final String BV_SEND_ERROR_IN_RESPONSE

Bean验证(JSR-349)支持自定义属性.如果设置为true且未明确禁用Bean Validation支持(请参阅BV_FEATURE_DISABLE),则验证错误信息将在返回的Response的实体中发送.

默认值为false.这意味着如果由Bean Validation错误导致错误响应,则默认情况下仅在服务器Response中发送状态代码.

配置属性的名称是"jersey.config.beanValidation.enableOutputValidationErrorEntity.server".

在你的 ResourceConfig

property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
Run Code Online (Sandbox Code Playgroud)

或者在你的web.xml中

<init-param>
    <param-name>
        jersey.config.beanValidation.enableOutputValidationErrorEntity.server
    <param-name>
    <param-value>true</param-value>
</init-param>
Run Code Online (Sandbox Code Playgroud)