MessageBodyReader не найден для типа media = application/octet-stream

Я пытаюсь получить json-данные из http://api.openweathermap.org/data/2.5/forecast/daily?lat=35&lon=139&cnt=10&mode=json с помощью следующего фрагмента кода:

private WebTarget getWebTarget() {
    Client client = JerseyClientBuilder.newClient();
    return client.target("http://api.openweathermap.org/")
            .path("data")
            .path("2.5");
}

// new one method
    Response response = getWebTarget()
                        .path("daily")
                        .queryParam("q", String.format("%s,%s", town, countryCode))
                        .queryParam("cnt", 10)
                        .queryParam("mode", "json")
                        .request().accept(MediaType.APPLICATION_JSON_TYPE).get();
    WeatherForecast forecast = response.readEntity(WeatherForecast.class);

Но последняя строка бросает:

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader не найден для типа носителя = application/octet-stream, тип = класс com.app.weather.providers.org.openweathermap.pojo.WeatherForecast, GenericType = класс com.app.weather.providers.org.openweathermap.pojo.WeatherForecast.

Зависимости Джерси в pom.xml:

<dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.13</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>2.4</version>
            <!-- use the following artifactId if you don't need servlet 2.x compatibility -->
            <!-- artifactId>jersey-container-servlet</artifactId -->
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-multipart</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json</artifactId>
            <version>2.0-m05-1</version>
        </dependency>

Этот код работает за пределами сервера приложений. Спасибо.

Ответ 1

Поддержка JSON Джерси поставляется в виде набора модулей расширения, где каждый из этих модулей содержит реализацию Feature, которая должна быть зарегистрирована в вашем экземпляре Configurable (клиент/сервер). Существует несколько фреймворков, которые обеспечивают поддержку обработки JSON и/или привязки JSON к Java. Модули, перечисленные ниже, обеспечивают поддержку представлений JSON путем интеграции отдельных структур JSON в Джерси. В настоящее время Джерси интегрируется со следующими модулями для поддержки JSON:

  • MOXy - поддержка привязки JSON через MOXy является стандартным и предпочтительным способом поддержки связывания JSON в ваших приложениях с Джерси с Джерси 2.0. Когда модуль JSON MOXy находится на пути к классу, Джерси автоматически обнаружит модуль и плавно включит поддержку привязки JSON через MOXy в ваших приложениях. (См. Раздел 4.3 "Возможности автоматического обнаружения".)
  • API Java для обработки JSON (JSON-P)
  • Джексон
  • отстрелить

для более подробной информации прочитайте главу 9 документации джерси.

Moxy - это предлагаемый метод поддержки json media. MOXy media module - один из модулей, где вам не нужно явно регистрировать его. Особенности (MoxyJsonFeature) в вашем клиенте/сервере. Настраивается, поскольку эта функция автоматически открывается и регистрируется, когда вы добавляете модуль jersey-media-moxy в свой класс-путь,

Чтобы использовать MOXy в качестве поставщика JSON, вам нужно добавить модуль jersey-media-moxy в файл pom.xml:

<dependency>
   <groupId>org.glassfish.jersey.media</groupId>
   <artifactId>jersey-media-moxy</artifactId>
   <version>2.15</version>
</dependency>

Если вы не используете Maven, убедитесь, что у вас есть все необходимые зависимости. см. jersey-media-moxy зависимости.
Вам нужно добавить этот файл jar в свой проект, чтобы поддерживать типы медиа json через jersey-media-moxy:

  • джерси-медиа-Moxy-2.15.jar
  • org.eclipse.persistence.core-2.5.0-rc2.jar
  • org.eclipse.persistence.antlr-2.5.0.jar
  • org.eclipse.persistence.moxy-2.5.0.jar
  • джерси-объект-фильтрация-2.3.1.jar

Использование:

некоторый обычный класс:

public class MyJAXBBean{

   private String name = "jack";
   private int id = 12;

   public MyJAXBBean() {

   }

   public String getName() {
       return this.name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getId() {
       return this.id;
   }

   public void setId(int id) {
       this.id = id;
   }
}

И основной класс для запуска примера jersey:

 public static void main(String[] args) {
    //ClientConfig cc = new ClientConfig().register(new JacksonFeature());
    Client client = ClientBuilder.newClient();
    WebTarget target = client.target("http://localhost:8084/myhost/test");

    Form form = new Form();
    form.param("x", "foo");
    form.param("y", "bar");

    MyJAXBBean bean;
    bean = target.request(MediaType.APPLICATION_JSON_TYPE)
            .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE),
                    MyJAXBBean.class);
    System.out.println(bean);
}

Ответ json сервера (http://localhost:8084/myhost/test) должен быть в следующем формате:

 {"name":"haleh", "id":3}

Ответ 3

У меня была аналогичная проблема, попробовав unmarshal JSON, обслуживаемую с типом мультимедиа "application/javascript". Я просто хотел бы внести свой вклад в оригинальный ответ, представив пример того, как я реализовал предлагаемое решение. Вы можете изменить тип носителя в соответствии с вашими потребностями.

@Provider
@Consumes("application/javascript")
public class MyMoxyJSONProvider extends MOXyJsonProvider {
    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return mediaType.equals(MediaType.valueOf("application/javascript"));
    }
}