Невозможно найти 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
вернуть этот объект).