ジャクソンプロバイダーで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);
}
_
あなたはあなたのmaven pomに次の依存関係を追加しようとすることができます。
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>2.3.4.Final</version>
</dependency>
問題は、実際にはRestEasyがJacksonプロバイダーを見つけられないことです。次のコードで手動で登録する必要がありました。
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-providers.jarに含まれていますが、同じファイルが別のjar、restasy-jaxrs.jarにも含まれています。これらの両方のjarを使用する実行可能なjarファイルの場合、マージされません。
私のコードを機能させるものは、私が追加したものです:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>&{resteasy.version}</version>
</dependency>
これ以外にも理由はわかりませんが、クライアントが作成されたときにRESTEASYがプロバイダーを初期化していないようです。つまり、手動でプロバイダーを初期化する必要がありました。
ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
RegisterBuiltin.register(instance);
instance.registerProvider(ResteasyJackson2Provider.class);
一般的には、クライアントを実行するだけで十分です。
同様の問題があり、resteasy-jackson-provider
のバージョンに関連していることがわかりました。 3.0.4.Final
から3.0.5.Final
に移動したところ、問題は解消しました。
さらに、3行目を次のように変更すると、依存関係を変更する必要がない結果が期待されたものであることがわかりました。
Response response = request.get(Object.class).toString();
JAX-RSが(GSONを手動で呼び出すのではなく)実際にシリアライゼーションを実行することの良さを回避したい場合は、StreamingOutput
を使用します(つまり、アウトプッターをStreamingOutput
としてラップし、そのオブジェクトを返します)。
その背後にある完全な根拠はわかりませんが、まったく同じ問題(複数回:P)が発生したため、MediaTypeをTEXT_PLAIN
に変更する必要があります。
または、JAX-RSに代わりにジョブを実行させることもできます。gson.toJSON(object)を実行する代わりに、単にオブジェクトを返し、メソッドシグネチャを任意のクラスに変更します。 JAX-RS(あなたの場合はRESTEasy)は自動的にジャクソンを呼び出し(正しく設定されている場合)、オブジェクトをjsonにシリアル化します。次に、クライアント側で、Stringの代わりに同じクラスを要求すると、すべてが独自に機能するはずです。 ClientRequest/Responseについては特に詳しくないので、私が言ったように機能しない可能性があります。代わりにクライアント側でRESTEasyプロキシ機能を使用します(ProxyFactory
を参照)。それにもかかわらず、JAX-RS/RESTEasyは、クライアント側でもjsonシリアライズ/デシリアライズを自動的に実行できるため、明確な方法があります。