如何使用 Jackson 修复 Jersey Client 的 MessageBodyProviderNotFoundException?

How to fix MessageBodyProviderNotFoundException with Jersey Client using Jackson?

我已经设置了一个使用 Jersey JSON 的 REST 客户端。首先根据 Baeldung's tutorial with MOXy and secondly according to Vaadin's tutorial 与 Jackson 的说法。

来自 REST 服务的 JSON 响应如下所示:

{
    "DisplayName": "Sixpack, Joe",
    "UserID": "joe.sixpack",
    "StdLog": "Some text"
}

所以我设置了一个简单的 JAXB bean ...

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class DisplayName {
    private String displayName;
    private String userID;
    private String stdLog;
    public DisplayName() {
    }

    public DisplayName(String DisplayName, String UserID, String StdLog) {
        this.displayName = DisplayName;
        this.userID = UserID;
        this.stdLog = StdLog;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getUserID() {
        return userID;
    }

    public void setUserID(String userID) {
        this.userID = userID;
    }

    public String getStdLog() {
        return stdLog;
    }

    public void setStdLog(String stdLog) {
        this.stdLog = stdLog;
    }
}

...添加了 Maven 依赖项...

<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.22.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.13</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.5</version>
</dependency>

...并实现了一个 REST 客户端:

Client client = ClientBuilder.newClient();
        URI uri = UriBuilder.fromUri("http://server:2000").path("/path/to/service/" + UriComponent.encode(input_parameter, UriComponent.Type.QUERY_PARAM_SPACE_ENCODED)).build();
        WebTarget target = client.target(uri);
        DisplayName responseDN = target.request(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).get(DisplayName.class);

然而,在使用 MOXy 媒体转换器时,无论根据类似问题(例如 JAX-RS Response Object displaying Object fields as NULL values, )使用的注释和构造函数(例如无参数构造函数)如何,所有 POJO 字段始终为空。

所以我想使用 Jackson 并改编 JAXB class ...

import com.fasterxml.jackson.annotation.*;

@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonPropertyOrder({"DisplayName","UserID","StdLog"})
public class DisplayName {
    @JsonProperty("DisplayName")
    private String displayName;
    @JsonProperty("UserID")
    private String userID;
    @JsonProperty("StdLog")
    private String stdLog;

    public DisplayName() {
    }

    @JsonCreator
    public DisplayName(@JsonProperty("DisplayName") String DisplayName, @JsonProperty("UserID") String UserID, @JsonProperty("StdLog") String StdLog) {
        this.displayName = DisplayName;
        this.userID = UserID;
        this.stdLog = StdLog;
    }

    public String getDisplayName() {
        return displayName;
    }

    @JsonProperty("DisplayName")
    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getUserID() {
        return userID;
    }

    @JsonProperty("UserID")
    public void setUserID(String userID) {
        this.userID = userID;
    }

    public String getStdLog() {
        return stdLog;
    }

    @JsonProperty("StdLog")
    public void setStdLog(String stdLog) {
        this.stdLog = stdLog;
    }
}

...并删除了 MOXy 依赖项并添加了 JAXB 的依赖项:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.25.1</version>
    </dependency>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>

但是,现在我运行进入了错误

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json

和 none 我找到的解决方案确实有帮助(例如 MessageBodyReader not found for media type=application/json, Glassfish :MessageBodyProviderNotFoundException in Jersy Client)。

为什么?解决方案是什么?

在我发布问题后不久,我在 Jersey User Guide 中找到了解释和解决方案,上面写着:

In order to use Jackson as your JSON (JAXB/POJO) provider you need to register JacksonFeature and a ContextResolver for ObjectMapper, if needed, in your Configurable (client/server).

由于 MOXy 是默认媒体库并自动注册到 WebClient,除非注册了另一个媒体库,否则将使用它。因此,必须注册 Jackson 媒体转换器 ...

Client client = ClientBuilder.newClient().register(JacksonFeature.class);

... 并添加相应的 Maven 依赖项:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.25.1</version>
</dependency>

令我惊讶的是,教程和类似问题的其他答案都没有提到它。