Невозможно найти MessageBodyReader типа содержимого application/json и типа java.lang.String.

Я использую клиент RestEasy с провайдерами Джексона и получаю вышеуказанную ошибку

клиентский код:

ClientRequest request = new ClientRequest(url);
request.accept(MediaType.APPLICATION_JSON);
ClientResponse<String> response = request.get(String.class);

if (response.getStatus() != 200) {
  throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}

BufferedReader br =
  new BufferedReader(new InputStreamReader(new ByteArrayInputStream(response.getEntity().getBytes())));

response.getEntity() бросает ClientResponseFailure исключение с ошибкой

Unable to find a MessageBodyReader of content-type application/json and type class java.lang.String

Мой код на стороне сервера ниже:

@GET
@Path("/{itemId}")
@Produces(MediaType.APPLICATION_JSON)
public String item(@PathParam("itemId") String itemId) {
  //custom code

  return gson.toJSON(object);
}

8 ответов

Вы можете попытаться добавить следующую зависимость в свой Maven Pom.

   <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson-provider</artifactId>
    <version>2.3.4.Final</version>
   </dependency>

Проблема в том, что RestEasy не может найти провайдера Джексона. Мне пришлось вручную зарегистрировать его с помощью следующего кода:

   ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
    RegisterBuiltin.register(instance);
    instance.registerProvider(ResteasyJacksonProvider.class);

Все работает нормально с этим. Но я все еще недоволен решением, так как Resteasy должен сканировать поставщиков и автоматически регистрировать их.

Client client = ClientBuilder.newBuilder().register(ResteasyJacksonProvider.class).build();

Простое добавление строки org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider в файл META-INF/services/javax.ws.rs.ext.Providers решает проблему.

Этот файл включен в resteasy-jackson-provider.jar, но тот же файл также включен в другой jar, restasy-jaxrs.jar, и для исполняемого файла jar, который использует оба этих jar, они не объединяются!!

У меня была похожая проблема, и я понял, что проблема связана с версией resteasy-jackson-provider, Я только что переехал из 3.0.4.Final в 3.0.5.Final и проблема исчезла.

Кроме того, я также понял, что если я изменю третью строку на следующую, результат будет ожидаемым без необходимости изменять зависимости.

Response response = request.get(Object.class).toString();

То, что заставило мой код работать, было то, что я добавил:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson2-provider</artifactId>
    <version>&{resteasy.version}</version>
</dependency>

Кроме того, я не знаю почему, но похоже, что не инициализируем провайдеров при создании клиента, это означает, что он должен был инициировать их вручную:

 ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
 RegisterBuiltin.register(instance);
 instance.registerProvider(ResteasyJackson2Provider.class);

В общем, достаточно запустить клиент.

Я не знаю полного обоснования этого, но мы столкнулись с одной и той же проблемой (несколько раз:P), и вам нужно изменить MediaType на TEXT_PLAIN,

Или вы также можете позволить JAX-RS сделать всю работу за вас: вместо того, чтобы делать gson.toJSON(объект), просто верните объект и измените сигнатуру вашего метода на любой другой класс. JAX-RS (RESTEasy в вашем случае) автоматически вызовет Джексона (если он правильно настроен) и сериализует ваш объект в json. Затем на стороне клиента вы бы запросили тот же класс вместо String, и все должно работать само по себе. Я не особенно знаком с ClientRequest/Response, поэтому он может не работать, как я сказал; вместо этого мы используем функцию прокси RESTEasy на стороне клиента (см. ProxyFactory). Тем не менее, JAX-RS/RESTEasy может автоматически выполнять сериализацию / десериализацию json на стороне клиента, так что, безусловно, есть выход.

Если вы действительно хотите обойти совершенство JAX-RS, фактически выполняя сериализацию для вас (вместо вызова GSON вручную), используйте StreamingOutput (т.е. обернуть выходной как StreamingOutputвернуть этот объект).

Другие вопросы по тегам