web-dev-qa-db-ja.com

メディアタイプ= application / jsonのMessageBodyReaderが見つかりません

JAX-RSサーバーとクライアントはどちらもJerseyを使用して作成しました。エンティティのコレクションをクライアントに送信したいので、次の手順を実行しました。

  1. 作成されたエンティティはSerializableを拡張します
  2. カスタムプロバイダーを作成し、コレクションをサポートするように拡張しました
  3. エンティティとプロバイダーをクライアント側にコピーアンドペーストします

私はリクエストを行いますが、クライアントがエラーを受信することでサーバー側で正常に処理されました:

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface Java.util.List, genericType=Java.util.List<model.HotelsEntity>.
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.Java:225)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.Java:149)
org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.Java:1124)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.Java:853)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.Java:812)
org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.Java:377)
org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.Java:813)
org.glassfish.jersey.client.JerseyInvocation.access$600(JerseyInvocation.Java:90)
org.glassfish.jersey.client.JerseyInvocation$3.call(JerseyInvocation.Java:693)
org.glassfish.jersey.internal.Errors.process(Errors.Java:315)
org.glassfish.jersey.internal.Errors.process(Errors.Java:297)
org.glassfish.jersey.internal.Errors.process(Errors.Java:228)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.Java:424)
org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.Java:689)
org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.Java:405)
org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.Java:301)
service.HotelService.getHotels(HotelService.Java:30)
actions.HotelAction.perform(HotelAction.Java:42)
MainServlet.processResponse(MainServlet.Java:33)
MainServlet.doPost(MainServlet.Java:22)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:641)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:722)

サーバ:

    @GET
@Produces(MediaType.APPLICATION_JSON)
public Response getHotelsList(@QueryParam("startDate") String startDate,
                              @QueryParam("endDate") String endDate) {
    List<HotelsEntity> list = hotelService.getAll();
    return ResponseFactory.response(Response.Status.OK, list);
}

クライアント:

    GenericType<List<HotelsEntity>> genericType = new GenericType<List<HotelsEntity>>(){};
    WebTarget target = client.target(preparePath());
    List<HotelsEntity> hotels = target.request(MediaType.APPLICATION_JSON_TYPE).get(genericType);

プロバイダー:

public class JsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> {

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

@Override
public T readFrom(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
    Gson gson = createGson();
    Reader reader = new InputStreamReader(entityStream, Charset.forName(Constants.UTF_8));
    return gson.fromJson(reader, genericType);
}

@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    return MediaType.APPLICATION_JSON.equals(mediaType.getType()) &&
            MediaType.APPLICATION_JSON.equals(mediaType.getSubtype());
}

@Override
public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    return -1;
}

@Override
public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
    Gson gson = createGson();
    JsonElement element = gson.toJsonTree(entityStream);
    Writer writer = null;
    try {
        writer = new OutputStreamWriter(entityStream, Charset.forName(Constants.UTF_8));
        gson.toJson(element, writer);
    } finally {
        if (writer != null) {
            writer.flush();
        }
    }
}

private Gson createGson() {
    return new GsonBuilder().setPrettyPrinting().create();
}

}

@Provider
public class JsonCollection extends JsonProvider<Collection<? extends HospitalityEntity>> {}

@Entity
@Table(name = "hotels", schema = "", catalog = "mydb")
public class HotelsEntity implements HospitalityEntity{
private int idHotel;
private String name;
private String region;
private String description;

@Id
@Column(name = "id_hotel")
public int getIdHotel() {
    return idHotel;
}

public void setIdHotel(int idHotel) {
    this.idHotel = idHotel;
}

@Basic
@Column(name = "name")
public String getName() {
    return name;
}

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

@Basic
@Column(name = "region")
public String getRegion() {
    return region;
}

public void setRegion(String region) {
    this.region = region;
}

@Basic
@Column(name = "description")
public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}


@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    HotelsEntity that = (HotelsEntity) o;

    if (idHotel != that.idHotel) return false;
    if (description != null ? !description.equals(that.description) : that.description != null) return false;
    if (name != null ? !name.equals(that.name) : that.name != null) return false;
    if (region != null ? !region.equals(that.region) : that.region != null) return false;

    return true;
}

@Override
public int hashCode() {
    int result = idHotel;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    result = 31 * result + (region != null ? region.hashCode() : 0);
    result = 31 * result + (description != null ? description.hashCode() : 0);
    return result;
}
}
27
user559730

Jersey jsonライブラリを使用できます。

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

またはゲンソン:

<dependency>
    <groupId>com.owlike</groupId>
    <artifactId>genson</artifactId>
    <version>1.3</version>
</dependency>
34
Deni35

この投稿を復活させて申し訳ありませんが、私はMavenプロジェクトでこの問題を抱えていたため、jackson-jaxrs-json-providerの依存関係をPOMに含める必要があることがわかりました。

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.4.1</version>
</dependency>

MVNリポジトリ: http://mvnrepository.com/artifact/com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider

23
CullenJ

エンティティクラスには、JAX-RSのアンマーシャリングに必要な空のコンストラクターがありません。

こちらをご覧ください:

https://blogs.Oracle.com/groundside/entry/jax_rs_2_0_messagebodyreader

12
blacharnia

JSONサポート用にメディアタイプを登録しているかどうかを確認します。クラスパスにjersey-media-moxyがありますか?そうでない場合は、pom.xmlにこの依存関係を追加し、ジャージのバージョンを確認してください。この例では、Jersey 2(2.24)を使用しています

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>2.24</version>
    </dependency>
7
brunocrt

Gradleの場合、次の依存関係を追加します。

compile group: 'org.glassfish.jersey.media',
name         : 'jersey-media-moxy',
version      : '2.24.1'
2
Purushothaman

このまったく同じ例外は、@XmlAttributeアノテーションが本当に@XmlElementを必要とするような愚かな間違いに対してjersey-media-moxyによってスローされます。私のシナリオではこれが当てはまり、特に問題が特定のクラスでのみ発生し、他のクラスで問題が発生する場合は、これを検討する必要があります。

0
user1932890