消息体提供程序未找到异常:未找到用于媒体类型text/html;charset=UTF-8的消息体读取器。

12

我正在尝试使用Openfire REST-API-Client。我正在使用以下代码调用方法,将用户添加到Openfire中。

AuthenticationToken authenticationToken = new AuthenticationToken("username","password");

RestApiClient restApiClient = new RestApiClient("url",port, authenticationToken);

UserEntity openFireUser = restApiClient.getUser(user.getUsername());

当我调用API时,我收到以下异常信息。

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/html;charset=UTF-8, type=class org.igniterealtime.restclient.entity.UserEntity, genericType=class org.igniterealtime.restclient.entity.UserEntity.
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:231)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:808)
    at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:326)
    at org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:115)

我谷歌了一下,看起来依赖项有些问题。但是没有任何作用。

以下是我的build.gradle文件


以下是我的build.gradle文件。

compile(group: 'org.igniterealtime', name :'rest-api-client', version: igniterealtime_rest_api_version){
        exclude group: 'org.slf4j', module: 'slf4j-simple'
        exclude group: 'org.slf4j', module: 'slf4j-api'
    }

我也尝试将以下依赖项添加到我的build.gradle中,但没有成功。

compile group: 'org.glassfish.jersey.core', name: 'jersey-client', version: '2.23'
compile group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.2'
compile group: 'org.glassfish.jersey.media', name: 'jersey-media-moxy', version: '2.24'
compile group: 'com.fasterxml.jackson.jaxrs', name: 'jackson-jaxrs-json-provider', version: '2.4.1'

4
你是否连接到了正确的URL?错误信息显示你收到的响应媒体类型为"text/html",显然无法解析为用户实体。这很可能是由于没有收到成功的响应(200 OK)或连接到了错误的URL导致的。 - Christoph Böhme
进行一些调试。检查状态码和响应体。在客户端反序列化之前检查状态码总是一个好主意,这样你可以在错误状态下执行其他操作。 - Paul Samsotha
遇到了问题。实际上我需要在Openfire中安装REST API插件。 - ajm
@ashishjmeshram - 遇到了同样的问题,在Java代码中进行REST调用 - 请求和响应都指定了content-type为application/json,但是却出现了异常org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/html;charset=UTF-8, type=interface java.util.Map, genericType=interface java.util.Map. 请问您是如何解决这个问题的? - mjs
@ChristophBöhme,谢谢!在我的情况下,这是由于错误的端点地址引起的!我一直围绕着这个错误转,直到我检查了另一个正常工作的服务(并且使用无效地址会导致相同的错误)。 - marcolopes
3个回答

3
问题出现是因为实体的 媒体类型text/html 不匹配。您可以使用 媒体类型为text/html 的restful服务,但需要使用 媒体类型为Application/json。还要检查请求的url和请求和响应的媒体类型。

同时使用

@Produces("application/json")
@Consumes(MediaType.APPLICATION_JSON)

并使用适当的状态码和Mediatype做出响应


2

首先,让我们看一下Jersey JAX-RS如何解析带有正确Content-Type:application/json的JSON响应。当它收到这样的响应时,它会查找任何可用的javax.ws.rs.ext.MessageBodyReader接口的实现,并对其进行注释:

@Consumes(MediaType.APPLICATION_JSON)

这可以是任何实现方式,但对于我们的示例,我们将MOXyJsonProvider添加为项目的依赖项:

最初的回答

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>${jersey.version}</version>
</dependency>

下一步,我们希望它也能处理Content-Type: text/plain响应。为此,我们同时从MOXyJsonProvider继承我们的自定义响应读取器,并使用MediaType.TEXT_PLAIN进行注释:
最初的回答:接下来,我们需要让它能够处理文本格式的响应,具体方法是继承自我们自定义的响应读取器MOXyJsonProvider,并在其上添加MediaType.TEXT_PLAIN的注释。
@Provider
@Consumes(MediaType.TEXT_PLAIN)
public class MyCustomResponseReader extends MOXyJsonProvider {

    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return genericType.equals(MyCustomClass.class);
    }

    @Override
    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
            InputStream entityStream) throws IOException, WebApplicationException {
        return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
    }

}

请注意,重写的readFrom()方法中我们只是调用了父类MOXyJsonProvider的super.readFrom()。
最后,我们需要在查询我们的Web服务的javax.ws.rs.client.Client实例中注册我们的自定义读取器:
Client client = ClientBuilder.newBuilder().build().register(MyCustomResponseReader.class);

现在,文本/纯文本响应将像任何应用程序/JSON响应一样被解析。

GitHub
完整的解决方案可以在GitHub上找到:PlainTextResponseReader

Credits
我基于以下资源中找到的信息构建了这个解决方案:

Stack Overflow
  • 创建一个 text/plain Jersey 响应
  • 如何在客户端注册我的自定义 MessageBodyReader?

  • Other
  • 编写自定义 MessageBodyReader 以处理 Jersey POST 请求体数据

  • 您正在从请求中读取文本以转换为后端对象。名称“MyCustomResponseReader”应更改为“MyCustomRequestReader”。 - Jeryl Cook
    @JerylCook:这是一个客户端的示例。它向服务器发送请求并将其响应转换为实体。因此需要响应读取器。为了使MyCustomRequestReader有意义,这应该是一个服务器应用程序。 - Denis Abakumov

    0

    我也遇到过同样的问题。这个 Bean 没有默认构造函数。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接