5.4. JAX-RS および RESTEasy アプリケーションの変更
JBoss EAP 6 は、JAX-RS 1.x の実装であった RESTEasy 2 をバンドルしました。
JBoss EAP 7.0 および JBoss EAP 7.1 には、JSR 339: JAX-RS 2.0: The Java API for RESTful Web Services 仕様で定義されている JAX-RS 2.0 の実装である RESTEasy 3.0.x が含まれていました。RESTful Web サービスの Java API に関する詳細情報は、 JAX-RS 2.0 API Specification を参照してください。
JBoss EAP 7.2 には RESTEasy 3.6.1 が含まれています。これは、JSR 370: Java(TM )API for RESTful Web Services (JAX-RS 2.1) Specification で定義されている JAX-RS 2.1 の実装です。本リリースでは、JDK 11 のサポートも追加されています。本リリースは RESTEasy 4 の主な機能の一部を提供しますが、ベースは RESTEasy 3.0 で、後方互換性を完全に維持します。そのため、RESTEasy 3.0.x から 3.6.1 への移行中に問題はほとんど発生しないはずです。RESTEasy 3.6.1 の Java API に関する詳細は、「RESTEasy JAX-RS 3.6.1.Final API」を参照してください。
JBoss EAP 6.4 から移行する場合、JBoss EAP に含まれる Jackson のバージョンが変更されたことに注意してください。JBoss EAP 6.4 には Jackson 1.9.9 が含まれていました。JBoss EAP 7 以上には Jackson 2.6.3 以上が含まれるようになりました。
本セクションでは、これらの変更が RESTEasy または JAX-RS を使用するアプリケーションに及ぼす可能性のある影響について説明します。
5.4.1. 非推奨の RESTEasy クラス
インターセプターおよび MessageBody クラス
JSR 311: JAX-RS: The Java™ API for RESTful Web Services にはインターセプターフレームワークが含まれなかったため、RESTEasy 2 によって提供されました。JSR 339: JAX-RS 2.0: The Java API for RESTful Web Services によって正式なインターセプターおよびフィルターフレームワークが導入されたため、RESTEasy 2 に含まれたインターセプターフレームワークは非推奨になり、RESTEasy 3.x の JAX-RS 対応インターセプターファシリティーに置き換えられました。関係するインターフェースは、 jaxrs-api
モジュールの javax.ws.rs.ext
パッケージに定義されます。
RESTEasy 3.x では、以下のインターセプターインターフェースが非推奨になりました。
-
org.jboss.resteasy.spi.interception.PreProcessInterceptor
インターフェースは RESTEasy 3.x のjavax.ws.rs.container.ContainerRequestFilter
インターフェースに置き換えられました。 RESTEasy 3.x では、以下のインターフェースとクラスも非推奨になりました。
-
org.jboss.resteasy.spi.interception.MessageBodyReaderInterceptor
-
org.jboss.resteasy.spi.interception.MessageBodyWriterInterceptor
-
org.jboss.resteasy.spi.interception.MessageBodyWriterContext
-
org.jboss.resteasy.spi.interception.MessageBodyReaderContext
-
org.jboss.resteasy.core.interception.InterceptorRegistry
-
org.jboss.resteasy.core.interception.InterceptorRegistryListener
-
org.jboss.resteasy.core.interception.ClientExecutionContextImpl
-
-
org.jboss.resteasy.spi.interception.MessageBodyWriterInterceptor
インターフェースはjavax.ws.rs.ext.WriterInterceptor
インターフェースに置き換えられました。 さらに、
javax.ws.rs.ext.MessageBodyWriter
インターフェースの変更の一部は JAX-RS 1.x の後方互換性を維持しない可能性があります。アプリケーションが JAX-RS 1.x を使用した場合はアプリケーションコードを確認し、エンドポイントに@Produces
または@Consumes
を定義するようにしてください。この定義を怠ると、以下のようなエラーが発生することがあります。org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: <OBJECT> of media type:
以下に、このエラーの原因となる REST エンドポイントの例を示します。
@Path("dates") public class DateService { @GET @Path("daysuntil/{targetdate}") public long showDaysUntil(@PathParam("targetdate") String targetDate) { DateLogger.LOGGER.logDaysUntilRequest(targetDate); final long days; try { final LocalDate date = LocalDate.parse(targetDate, DateTimeFormatter.ISO_DATE); days = ChronoUnit.DAYS.between(LocalDate.now(), date); } catch (DateTimeParseException ex) { // ** DISCLAIMER **. This example is contrived. throw new WebApplicationException(Response.status(400).entity(ex.getLocalizedMessage()).type(MediaType.TEXT_PLAIN) .build()); } return days; } }
この問題を修正するには、次のように
javax.ws.rs.Produces
のインポートと@Produces
アノテーションを追加します。... import javax.ws.rs.Produces; ... @Path("dates") public class DateService { @GET @Path("daysuntil/{targetdate}") @Produces(MediaType.TEXT_PLAIN) public long showDaysUntil(@PathParam("targetdate") String targetDate) { DateLogger.LOGGER.logDaysUntilRequest(targetDate); final long days; try { final LocalDate date = LocalDate.parse(targetDate, DateTimeFormatter.ISO_DATE); days = ChronoUnit.DAYS.between(LocalDate.now(), date); } catch (DateTimeParseException ex) { // ** DISCLAIMER **. This example is contrived. throw new WebApplicationException(Response.status(400).entity(ex.getLocalizedMessage()).type(MediaType.TEXT_PLAIN) .build()); } return days; } }
RESTEasy の以前のリリースからのインターセプターはすべて、新規の JAX-RS フィルターおよびインターセプターインターフェースと並行して実行することが可能です。
インターセプターの詳細情報は、JBoss EAP『Developing Web Services Applications』の「RESTEasy Interceptors」を参照してください。
新しい代替の API は、RESTEasy JAX-RS 3.6.1.Final API を参照してください。
クライアント API
resteasy-jaxrs
の RESTeasy クライアントフレームワークは、JBoss EAP 7.0 で JAX-RS 2.0 準拠の resteasy-client
モジュールに置き換えられました。そのため、RESTEasy クライアント API クラスおよびメソッドの中には非推奨となっているものもあります。
以下のクラスは非推奨になりました。
-
org.jboss.resteasy.client.ClientResponseFailure
例外、org.jboss.resteasy.client.ClientExecutor
インターフェースおよびorg.jboss.resteasy.client.EntityTypeFactory
インターフェースも非推奨になりました。 org.jboss.resteasy.client.ClientRequest
およびorg.jboss.resteasy.client.ClientResponse
クラスを、それぞれorg.jboss.resteasy.client.jaxrs.ResteasyClient
およびjavax.ws.rs.core.Response
に置き換える必要があります。以下は RESTEasy 2.3.x の RESTEasy クライアントでリンクヘッダーを送信する例です。
ClientRequest request = new ClientRequest(generateURL("/linkheader/str")); request.addLink("previous chapter", "previous", "http://example.com/TheBook/chapter2", null); ClientResponse response = request.post(); LinkHeader header = response.getLinkHeader();
以下は RESTEasy 3 の RESTEasy クライアントで上記と同じタスクを実行する例です。
ResteasyClient client = new ResteasyClientBuilder().build(); Response response = client.target(generateURL("/linkheader/str")).request() .header("Link", "<http://example.com/TheBook/chapter2>; rel=\"previous\"; title=\"previous chapter\"").post(Entity.text(new String())); javax.ws.rs.core.Link link = response.getLink("previous");
JAX-RS Web サービスと対話する外部 JAX-RS RESTEasy クライアントの例は、
resteasy-jaxrs-client
クイックスタートを参照してください。-
org.jboss.resteasy.client.cache
パッケージのクラスおよびインターフェースも非推奨になりました。これらのクラスとインターフェースは、org.jboss.resteasy.client.jaxrs.cache
パッケージの同等のクラスおよびインターフェースに置き換えられました。
org.jboss.resteasy.client.jaxrs
API クラスの詳細については、RESTEasy JAX-RS JavaDoc を参照してください。
StringConverter
org.jboss.resteasy.spi.StringConverter
クラスは RESTEasy 3.x では非推奨になりました。この機能は JAX-RS の jax.ws.rs.ext.ParamConverterProvider クラスを使用して置き換えできます。
5.4.2. 削除または保護されている RESTEasy クラス
ResteasyProviderFactory Add メソッド
org.jboss.resteasy.spi.ResteasyProviderFactory
add()
メソッドのほとんどは、RESTEasy 3.0 で削除または保護されました。たとえば、addBuiltInMessageBodyReader()
および addBuiltInMessageBodyWriter()
メソッドは削除され、 addMessageBodyReader()
および addMessageBodyWriter()
メソッドは保護されました。
現時点では、registerProvider()
と registerProviderInstance()
のメソッドを使用してください。
RESTEasy 3 から削除された他のクラス
@org.jboss.resteasy.annotations.cache.ServerCached
アノテーションは、JAX-RS メソッドへの応答をサーバーでキャッシュすることを指定するものでしたが、これは RESTEasy 3 から削除されたので、アプリケーションコードから削除する必要があります。
5.4.3. 他の RESTEasy 変更点
SignedInput および SignedOuput
-
resteasy-crypto
のSignedInput
およびSignedOutput
では、Content-Type
をRequest
またはResponse
オブジェクトのいずれかでmultipart/signed
に設定する必要があります。 そうでない場合は、@Consumes
または@Produces
アノテーションを使用する必要があります。 -
SignedOutput
およびSignedInput
を使用すると、@Produces
または@Consumes
アノテーションでapplication/pkcs7-signature
MIME タイプを設定して、そのタイプの形式をバイナリ形式で返すことができます。 -
@Produces
または@Consumes
がtext/plain
MIME タイプの場合、SignedOutput
は base64 でエンコードされ、文字列として送信されます。
セキュリティーフィルター
@RolesAllowed
、@PermitAll
、および @DenyAll
のセキュリティーフィルターは、"401 Unauthorized" ではなく "403 Forbidden" を返すようになりました。
クライアント側のフィルター
RESTEasy 3.0 より前のリリースから RESTEasy クライアント API を使用している場合は、JAX-RS 2.0 で導入されたクライアント側のフィルターはバインドされず、実行されません。
非同期 HTTP サポート
JAX-RS 2.0 仕様は、@Suspended
アノテーションと AsynResponse
インターフェースを使用した非同期 HTTP サポートを追加したため、非同期 HTTP の RESTEasy プロプライエタリー API は非推奨となりました。今後の RESTEasy リリースで削除される可能性があります。非同期 Tomcat と非同期 JBoss Web モジュールもサーバーインストールから削除されています。 Servlet 3.0 コンテナーまたはそれ以降を使用していない場合、非同期 HTTP サーバー側の処理がシミュレートされ、同一リクエストスレッドで同期的に実行されます。
サーバー側のキャッシュ
サーバー側のキャッシュ設定が変更されました。詳細は、「RESTEasy Documentation」を参照してください。
YAML プロバイダーの設定変更
以前のリリースの JBoss EAP では、RESTEasy YAML プロバイダー設定はデフォルトで有効になっていました。これは JBoss EAP 7 で変更になりました。YAML プロバイダーがデフォルトで無効化されるようになりました。アンマーシャリングで RESTEasy によって使用される SnakeYAML
ライブラリーにセキュリティー上の問題があるため、YAML プロバイダーの使用はサポートされず、アプリケーションで明示的に有効にする必要があります。アプリケーションで YAML プロバイダーを有効にし、Maven 依存関係を追加する方法は、JBoss EAP『Developing Web Services Applications』の「YAML Provider」を参照してください。
Content-Type ヘッダーのデフォルトの文字セット UTF-8
JBoss EAP 7.1 より、デフォルトで resteasy.add.charset
パラメーターが true
に設定されています。リソースメソッドが明示的な文字セットなしで text/*
または application/xml*
メディアタイプを返すときに、返された content-type ヘッダーに charset=UTF-8
を追加したくない場合は、resteasy.add.charset
パラメーターを false
に設定できます。
テキストメディアタイプと文字セットの詳細は、JBoss EAP『Developing Web Services Applications』の「Text Media Types and Character Sets」を参照してください。
SerializableProvider
信用できないソースから Java オブジェクトをデシリアライズすることは危険です。そのため、JBoss EAP 7 では org.jboss.resteasy.plugins.providers.SerializableProvider
クラスがデフォルトで無効となり、このプロバイダーの使用は推奨されません。
リソースメソッドへのリクエストの一致
RESTEasy 3 では、JAX-RS 仕様の定義どおりに、一致ルールの実装に改善および修正が加えられました。特に、サブリソースメソッドおよびサブリソースロケーターのあいまいな URI の処理方法が変更されました。
RESTEasy 2 では、同じ URI を持つ別のサブリソースが存在していても、サブリソースロケーターが正常に実行される可能性がありました。仕様上ではこの挙動は適切ではありません。
RESTEasy 3 では、サブリソースおよびサブリソースロケーターのあいまいな URI が存在する場合、サブリソースの呼び出しには成功しますが、サブリソースロケーターの呼び出しは HTTP ステータス 405 Method Not Allowed
のエラーによって失敗します。
以下の例には、サブリソースメソッドおよびサブリソースロケーターのあいまいな @Path
アノテーションが含まれています。エンドポイント anotherResource
および anotherResourceLocator
両方の URI は同じであることに注目してください。この 2 つのエンドポイントの違いは、anotherResource
メソッドは REST 動詞である POST
に関連付けられていることです。anotherResourceLocator
メソッドに関連付けられている REST 動詞はありません。仕様上では、REST 動詞を持つエンドポイント (この場合は anotherResource
メソッド) が常に選択されます。
@Path("myResource") public class ExampleSubResources { @POST @Path("items") @Produces("text/plain") public Response anotherResource(String text) { return Response.ok("ok").build(); } @Path("items") @Produces("text/plain") public SubResource anotherResourceLocator() { return new SubResource(); } }
リソースメソッドアルゴリズムの切り替え
3.0.25.Final より前の RESTEasy 3.0.x バージョンで使用されたリソースメソッド一致アルゴリズムでバグが見つかりました。このバグにより、リクエストの応答時に RESTEasy は余分なリソースメソッドを返しました。
一致アルゴリズムには 3 つの手順があります。
- リクエストパスを使用して可能なリソースクラスを選択する。
- リクエストパスを使用して可能なリソースメソッドを選択する。
- 送受信で HTTP 動詞とメディアタイプを使用して最終的なリソースメソッドを選択する。
JAX-RS 2.0 仕様によると、潜在的なリソースメソッドセットのソート後に最大要素のみを手順 3 に渡す必要があります。しかし、RESTEasy 3.0.25 より前の RESTEasy 3.0.x 実装はすべてのメソッドを手順 3 に渡しました。JBoss EAP 7.1.0 に含まれる RESTEasy 3.0.24 は、この不適切な動作を実行します。
JBoss EAP 7.1.1 に含まれる RESTEasy 3.0.25 は、JAX-RS 2.0 仕様に準拠するために手順 3 に渡すメソッドを制限する修正を提供します。厳格でない動作が望ましい場合もあるため、RESTEasy 3.0.25 にはこれまでの動作を有効にできる context-param
設定オプションの resteasy.loose.step2.request.matching
も導入されました。 これはデフォルトで false
に設定されています。
JBoss EAP サーバーを 7.1.0 から 7.1.1 に更新し、これまでの動作を維持して潜在的なリソースメソッドをすべて手順 3 に渡す場合は、resteasy.loose.step2.request.matching
オプションを true
に設定します。
一致アルゴリズムは、一致したすべてのリソースメソッドを手順 3 に渡すよう JAX-RS 2.1 で変更になりました。JBoss EAP 7.2 に含まれている RESTEasy 3.6.1 は、JAX-RS 2.0 仕様で定義されている厳格な動作を維持する jaxrs.2.0.request.matching
オプションを提供します。
アプリケーションを JBoss EAP 7.1.0 から 7.2.x に移行した場合、リソースメソッドの一致アルゴリズムの動作は変更されません。アプリケーションを JBoss EAP 7.1.1 から 7.2.x に移行し、JAX-RS 2.0 仕様に定義されている厳格な動作を維持したい場合は、jaxrs.2.0.request.matching
オプションを true
に変更します。
5.4.4. RESTEasy SPI の変更点
SPI 例外
すべての SPI 失敗例外は非推奨となり、内部的には使用されません。これらは対応する JAX-RS 例外に置き換えられました。
非推奨の例外 | jaxrs-api モジュールでの代替の例外 |
---|---|
org.jboss.resteasy.spi.ForbiddenException | javax.ws.rs.ForbiddenException |
org.jboss.resteasy.spi.MethodNotAllowedException | javax.ws.rs.NotAllowedException |
org.jboss.resteasy.spi.NotAcceptableException | javax.ws.rs.NotAcceptableException |
org.jboss.resteasy.spi.NotFoundException | javax.ws.rs.NotFoundException |
org.jboss.resteasy.spi.UnauthorizedException | javax.ws.rs.NotAuthorizedException |
org.jboss.resteasy.spi.UnsupportedMediaTypeException | javax.ws.rs.NotSupportedException |
InjectorFactory および Registry
InjectorFactory
および Registry
SPI が変更されました。ドキュメントに従ってサポートされるように RESTEasy を使用する場合は、問題はありません。
5.4.5. Jackson プロバイダーの変更
JBoss EAP に含まれる Jackson のバージョンは変更されました。JBoss EAP の以前のリリースに含まれていた Jackson は 1.9.9 でした。JBoss EAP 7 には Jackson 2.6.3 またはそれ以降が含まれています。このため、Jackson プロバイダーが resteasy-jackson-provider
から resteasy-jackson2-provider
に変更されました。
resteasy-jackson2-provider
へのアップグレードにはいくつかのパッケージ変更が必要になります。たとえば、Jackson アノテーションパッケージは org.codehaus.jackson.annotate
から com.fasterxml.jackson.annotation
に変更されました。
JBoss EAP の以前のリリースに含まれていたデフォルトのプロバイダーを使用するようにアプリケーションを切り替えるには、JBoss EAP『Developing Web Services Applications』の「Switching the Default Jackson Provider」を参照してください。
5.4.6. Spring と RESTEasy の統合の変更
Spring 4.0 フレームワークには、Java 8 のサポートが導入されました。Spring と RESTEasy 3.x 統合を使用する場合は、使用するデプロイメントで最小 Spring バージョンに 4.2.x を指定してください。 これは JBoss EAP 7 がサポートする安定性のある最も早期のバージョンです。
5.4.7. RESTEasy Jettison JSON プロバイダーの変更
RESTEasy Jettison JSON プロバイダーは JBoss EAP 7 では非推奨となり、デフォルトでデプロイメントに追加されなくなりました。推奨される RESTEasy Jackson プロバイダーに切り替えるようにしてください。Jettison プロバイダーの使用継続を希望する場合は、以下の例で示すように jboss-deployment-descriptor.xml
ファイルでその明示的な依存関係を定義する必要があります。
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure> <deployment> <exclusions> <module name="org.jboss.resteasy.resteasy-jackson2-provider"/> <module name="org.jboss.resteasy.resteasy-jackson-provider"/> </exclusions> <dependencies> <module name="org.jboss.resteasy.resteasy-jettison-provider" services="import"/> </dependencies> </deployment> </jboss-deployment-structure>
明示的な依存関係の定義方法については、JBoss EAP『開発ガイド』の「デプロイメントへの明示的なモジュール依存関係の追加」を参照してください。