Java EE 7...

58
© 2015 IBM Corporation Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 JAX-RS: The Java API for RESTful Web Services 日本アイ・ビー・エム システムズ・エンジニアリング株式会社

Transcript of Java EE 7...

Page 1: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 JAX-RS: The Java API for RESTful Web Services

日本アイ・ビー・エム システムズ・エンジニアリング株式会社

Page 2: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

Disclaimer

この資料は日本アイ・ビー・エム株式会社ならびに日本アイ・ビー・エム システムズ・エンジニアリング株式会社の正式なレビューを受けておりません。

当資料は、資料内で説明されている製品の仕様を保証するものではありません。 資料の内容には正確を期するよう注意しておりますが、この資料の内容は2014年12月現在の情報であり、製品の新しいリ

リース、PTFなどによって動作、仕様が変わる可能性があるのでご注意下さい。 今後国内で提供されるリリース情報は、対応する発表レターなどでご確認ください。 IBM、IBMロゴおよびibm.comは、世界の多くの国で登録されたInternational Business Machines

Corporationの商標です。他の製品名およびサービス名等は、それぞれIBMまたは各社の商標である場合があります。現時点でのIBMの商標リストについては、www.ibm.com/legal/copytrade.shtmlをご覧ください。

当資料をコピー等で複製することは、日本アイ・ビー・エム株式会社ならびに日本アイ・ビー・エム システムズ・エンジニアリング株式会社の承諾なしではできません。

当資料に記載された製品名または会社名はそれぞれの各社の商標または登録商標です。 JavaおよびすべてのJava関連の商標およびロゴは Oracleやその関連会社の米国およびその他の国における商標または登録

商標です。 Microsoft, Windows および Windowsロゴは、Microsoft Corporationの米国およびその他の国における商標です。 Linuxは、Linus Torvaldsの米国およびその他の国における登録商標です。 UNIXはThe Open Groupの米国およびその他の国における登録商標です。

2

Page 3: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

目次

1. はじめに

2. 概要

3. JAX-RS アプリケーションの開発

4. JAX-RS クライアントの開発

5. 非同期処理

6. プロバイダーの開発

7. まとめ

8. 参考資料

3

Page 4: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

1. はじめに

Page 5: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

Java EE 7 に含まれる仕様 (JSR一覧)

Java EE 7 では、4つの仕様が新規に追加され、3つの仕様がバージョンアップされている

当ガイドでは、Java EE 7 で大幅に機能拡張された JAX-RS 2.0 を対象とする

CDI Extensions

CDI 1.1

Managed Beans 1.0

JPA 2.1 JMS 2.0 JCA 1.7

Common Annotations 1.1

EJB 3.2

Servlet 3.1

Concurrency 1.0

Batch 1.0

WebSocket 1.0

JSON 1.0 Web

Fragments

JSF 2.2 JSP 2.3 EL 3.0

Bea

n V

ali

da

tio

ns

1.1

JAX-RS 2.0

JAX-WS 2.2

Interceptors 1.2

JTA 1.2

5

Page 6: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

WebSphere Application Server のサポート状況 (2015年3月現在)

V8.5.5.5 までは JAX-RS 2.0 に未対応

–Full Profile および Liberty Profile 共に対応していない

Liberty Profile Beta が JAX-RS 2.0 に対応

–Liberty Beta は下記URLからダウンロード可能

• https://developer.ibm.com/wasdev/

– JAX-RS 2.0 を使用する場合は、Java SE 7 以降が前提

Liberty Profile Beta は JSON-P にも対応

– JAX-RS 2.0 の JSON データの処理に JSON-P が使用可能

–Liberty Profile では V8.5.5.4 以降で JSON-P に対応済み

6 JSON-P: Java API for JSON Processing

Page 7: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

2. 概要

Page 8: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

Web サービス

プラットフォームに依存しない分散コンピューティング技術

–Web → インターネットの技術を利用、プラットフォー非依存

–サービス → ソフトウェア・コンポーネントが提供する機能、業務ロジック

Java EE 7 では2つの Web サービスの仕様をサポート

JAX-WS

–従来型の Web サービスの仕様

• インターフェースを WSDL で記述 (WSDL は XML 形式のインターフェース記述言語)

• メッセージ・フォーマットとして SOAP を利用 (SOAP は XML 形式のメッセージを使用し、通信プロトコルに依存しない)

JAX-RS

–新しい形態の Web サービスの仕様

• ソフトウェア・アーキテクチャのスタイルの1つである REST に従う

– 「RESTful Web サービス」と呼ばれる

8

クライアント (リクエスター)

Webサービス

リクエスト

レスポンス

REST: Representational State Transfer

Page 9: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

RESTful Web サービス

リソース指向

–リソースは Web で共有する任意のデータ

–リソースは一意な URI を持つ

• 例:http://host.jp/jaxrs/employee/E220

リソースに対する操作を HTTP メソッドで表現

–GET 取得

–PUT 更新、または、追加

–POST 追加

–DELETE 削除

Stateless な呼び出しプロトコル

9

Employee サービス

社員 ID=E63 氏名=… 所属=… ……=…

GET …/employee?country=jp

社員 ID=E220 氏名=… 所属=… ……=…

社員 ID=E250 氏名=… 所属=… ……=…

200 OK

GET …/employee/E220

200 OK ID=E220 氏名=…

一覧

PUT …/employee/E250

200 OK

ID=E250 氏名=…

GET …/employee/E250

200 OK ID=E250 氏名=…

クライアント

ある社員の

情報を取得

別の社員の

情報を取得

社員の情報を

更新

jp の社員を

照会

Page 10: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

JAX-RS 2.0 の主な新機能

JAX-RS クライアント機能の追加

–クライアント側でも非同期処理をサポート

非同期処理のサポート

Bean Validation 対応

プロバイダー機能の拡充

–エンティティー・インターセプターの追加

–フィルター機能の追加

10

Page 11: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

3. JAX-RS アプリケーションの開発

Page 12: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

JAX-RS アプリケーションの構成要素

以下の、3つの要素で構成される

javax.ws.rs.core.Application のサブクラス

– JAX-RS アプリケーションを構成するリソース・クラスやプロバイダーなどの情報を JAX-RS ランタイムに提供

– JAX-RS アプリケーション毎に1つ作成

リソース・クラス

–RESTful Web サービスとしてアクセスされる Web リソース用のクラス

– JAX-RS アプリケーションの本体で、ビジネス・ロジックを実装

プロバイダー

– JAX-RS ランタイムを拡張するための機能 (必要に応じて作成)

–プロバイダーの種類

• エンティティー・プロバイダー

• コンテキスト・プロバイダー

• 例外マッピング・プロバイダー

• パラメーター・コンバーター・プロバイダー

• エンティティー・インターセプター

• フィルター

JAX-RS アプリケーション

Application のサブクラス

リソース・クラス

プロバイダー

リソース・クラス リソース・クラス

プロバイダー

12

Page 13: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

javax.ws.rs.core.Application のサブクラス

JAX-RS アプリケーションの構成情報を JAX-RS ランタイムに提供する役割を担う

–もっとも単純な構成

• war モジュール内に存在する全てのリソース・クラスとプロバイダーを使用して、JAX-RS アプリケーションを構成する

–リソース・クラスやプロバイダーを制限したい場合や、明示的に指定する必要がある場合

• 指定したリソース・クラスとプロバイダーを使用して、JAX-RS アプリケーションを構成する

package jax.rs.test; @javax.ws.rs.ApplicationPath("/jaxrs") public class Application extends javax.ws.rs.core.Application {}

package jax.rs.test; @javax.ws.rs.ApplicationPath("/jaxrs") public class Application extends javax.ws.rs.core.Application { @Override public java.util.Set<Class<?>> getClasses() { java.util.HashSet<Class<?>> set = new java.util.HashSet<Class<?>>(); set.add( Hello.class ); set.add( xxxxx ); return set; } }

•@javax.ws.rs.ApplicationPath アノテーションで JAX-RS アプリケーションのパスを指定 •何も実装する必要はない

•@javax.ws.rs.ApplicationPath アノテーションで JAX-RS アプリケーションのパスを指定 •getClasses() をオーバーライドして、必要なリソース・クラスとプロバイダーのみを返す

13

Page 14: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

補足:javax.ws.rs.core.Application のサブクラス

以下の3種類の情報を提供

– JAX-RS ランタイムにリソース・クラスやプロバイダーなどの情報を提供

• Set<Class<?>> getClasses() メソッド

• Set<Object> getSingletons() メソッド

– JAX-RS アプリケーションのカスタム・プロパティーを提供

• Map<String,Object> getProperties() メソッド

• アプリケーション・レベルで構成情報などを共有するために使用できる

• 「@Context Application 」 アノテーションで、リソース・クラスのフィールドやメソッドのパラメーターなどにインジェクション可能

– JAX-RS アプリケーションのパス

• @javax.ws.rs.ApplicationPath アノテーション

14

Page 15: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

web.xml を使用した JAX-RS アプリケーションの構成

javax.ws.rs.core.Application のサブクラスを作成しない方法

–war モジュール内に存在する全てのリソース・クラスとプロバイダーを使用して、JAX-RS アプリケーションが構成される

その他の方法

– javax.ws.rs.core.Application のサブクラスを定義し、パスのみを web.xml で指定する方法もある

ポータビリティーの観点からは、 javax.ws.rs.core.Application のサブクラスのみで済ませるのが良い。

<servlet> <servlet-name>javax.ws.rs.core.Application</servlet-name> </servlet> <servlet-mapping> <servlet-name>javax.ws.rs.core.Application</servlet-name> <url-pattern>/jaxrs/*</url-pattern> </servlet-mapping>

•既定のサーブレット名 javax.ws.rs.core.Application と、そのマッピングを追加する •ここで指定したマッピングが JAX-RS アプリケーションのパスとなる

15

Page 16: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

リソース・クラス

Web リソース用のクラスで、POJO に JAX-RS アノテーションを付与して開発

• アノテーションは、javax.ws.rs パッケージ内に存在

–@Path

• リソース・クラスやリソース・メソッドに付与し、リソースの URI を指定する

• クラスとメソッドの両方に指定した場合は、両方を連結した URI が使用される

–@GET, @POST, @PUT, @DELETE, @HEAD, @OPTIONS

• 対応する HTTP リクエストを処理するリソース・メソッドであることを示す

• 1リソース・メソッドは1HTTPメソッドに対応

• リソース・メソッドは public なメソッド

インスタンスの生成と破棄

–要求の度に新しいインスタンスが生成され、再利用されない。

package jax.rs.test; import javax.ws.rs.*; @Path("employee") public class EmployeeResourceMgr { @GET public Response list(){ // 全社員の情報を返す } @POST public Response addEmp( ・・・ ){ // 新しい社員を追加する } }

•リソースの URI は "/<warのコンテキスト・ルート>/<JAX-RSアプリのパス>/employee" となる •この URI に対する GET リクエストで、list() メソッドが呼び出される •この URI に対する POST リクエストで、 addEmp() メソッドが呼び出される

16

リソース・クラス

リソース・メソッド

Page 17: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

@Path アノテーションでの URI パス・テンプレートの使用

URI にパス・パラメーター(変数)を含めることで、URI パスのテンプレート化が行える

• 例:@Path("{id}")

• 例:@Path("{company}/{department}")

• 例:@Path("Dept_{deptCode}")

–パス・パラメーターにマッチさせる範囲を正規表現で指定できる

• 例:@Path("{id: [a-zA-Z][a-zA-Z0-9]*}") 英字で始まり、英字と数値が繰り返されるものにマッチ

• 例:@Path("{path:.+}") パスの区切りを無視して、任意の文字に最後までマッチ

–正規表現を省略すると、 "[^/]+?" を指定したことになり、"/" 以外の文字列にマッチする

サブ・リソース・メソッド(サブ・リソースを処理するメソッド)と組み合わせて使用することが多い

@Path("employee") public class EmployeeResourceMgr { @GET public Response list(){ // 全社員の情報を返す } @POST public Response addEmp( ・・・ ){ // 新しい社員を追加する } @Path("{id:[A-Z][0-9]+}") @GET public Response queryEmp( ・・・ ) { // 指定された社員の情報を返す } @Path("{id:[A-Z][0-9]+}") @PUT public Response updateEmp( ・・・ ) { // 指定された社員の情報を更新する } }

•URI は "…/employee/E220" や "…/employee/E350" などの形式となる •このうち、"E220" や "E350" が、パス・パラメーター id にマップされる •@Path アノテーションが付与された、この形式のメソッドを、サブ・リソース・メソッドと呼ぶ

17

リソース・クラス

リソース・メソッド

サブ・リソース・メソッド

Page 18: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

補足:URI パスのマッチングの優先順位

リクエストが、複数のリソース・メソッドにマッチする場合は、以下の順で呼び出されるメソッドが決定される

–マッチする文字数が多い順

–パス・テンプレートの数が多い順

–正規表現によるマッチングを使用したパス・テンプレートの数が多い順

18

Page 19: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

サブ・リソース・ロケーター

サブ・リソースの処理を別のリソース・クラスに委譲することが可能

–サブ・リソース・ロケーターを使用した実装

public class EmployeeResource { private String empNo; public EmployeeResource( String empNo ) { this.empNo = empNo; } @GET public Response queryEmp() { // 指定された社員の情報を返す } @PUT public Response updateEmp( Employee emp ) { // 指定された社員の情報を更新する } }

@Path("employee") public class EmployeeResourceMgr { @GET public Response list(){ // 全社員の情報を返す } @POST public Response addEmp( ・・・ ){ // 新しい社員を追加する } @Path("{id:[A-Z][0-9]+}") public EmployeeResource processEmp( @PathParam("id") String empNo ) { return new EmployeeResource( empNo ); } }

•@Path でサブ・リソースの URI を指定する。@GET, @POST などのアノテーションは付与しない •戻り値として、サブ・リソース・クラスのインスタンスを返す。この時、サブ・リソースへのデータの引き継ぎが必要となる •この形式のメソッドを、サブ・リソース・ロケーターと呼ぶ

リソース・クラス サブ・リソース・クラス

•@Path アノテーションは付与しない •@GET, @POST などを対応するメソッドに付与

19

リソース・メソッド

サブ・リソース・ロケーター

Page 20: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

リソース・クラスやリソース・メソッドへのインジェクション(1)

リクエストなどに関連する情報を、リソース・メソッドのパラメーターにインジェクションできる

• @QueryParam URI 照会パラメーターの値

• @MatrixParam URI マトリックス・パラメーターの値

• @PathParam URI のパス・パラメーターの値

• @HeaderParam ヘッダーの値

• @CookieParam クッキーの値

• @FormParam フォーム・パラメーターの値 (リソース・メソッドの場合のみ使用可)

• アノテーションは、javax.ws.rs パッケージ内に存在

–@DefaultValue を併用することでデフォルト値の指定が可能

–@XxxxParam によるインジェクション先は、文字列型またはプリミティブ型が基本

• 特殊な型への変換は、パラメーター・コンバーターの実装が必要

• 変換でエラーになると、404 や 400 がクライアントに返る

–リソース・クラスのフィールドやプロパティーへのインジェクションも可能

@Path("employee") public class EmployeeResourceMgr { ・・・ @GET public Response list( @QueryParam("country") String cntry ){ // 条件に一致する社員の情報を返す } @Path("{id:[A-Z][0-9]+}") @GET public Response queryEmp( @PathParam("id") String empNo ) { // 指定された社員の情報を返す } ・・・ }

•パス・パラメーター id の値が、 メソッド・パラメーター empNo にインジェクションされる

•URIの例: …/employee?country=jp •照会パラメーター country の値が、 メソッド・パラメーター cntry にインジェクションされる

20

Page 21: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

リソース・クラスやリソース・メソッドへのインジェクション(2)

@Context アノテーションで、以下のコンテキストをリソース・メソッドのパラメーターにインジェクションできる • アノテーションは、javax.ws.rs.core パッケージ内に存在

–Application

• アプリケーションが提供した javax.ws.rs.core.Application サブクラスのインスタンス

• JAX-RS アプリケーションのカスタム・プロパティーにアクセスできるので、アプリケーションの構成情報を管理するために使用できる

–UriInfo

• リクエストの URI の情報を提供

–HttpHeaders

• HTTP リクエストのヘッダー情報を提供

–SecurityContext

• セキュリティー・コンテキストを提供

–ServletConfig, ServletContext, HttpServletRequest, HttpServletResponse

• サーブレット・コンテナ上で稼動する場合にのみインジェクション可能

–リソース・クラスのフィールドやプロパティーへのインジェクションも可能

21

Page 22: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

リソース・メソッドのエンティティー・パラメーター

エンティティー・パラメーター

–@QueryParam などの前述のアノテーションが付与されていないリソース・メソッドのパラメーター

–HTTP リクエストのメッセージ・ボディー(エンティティー・ボディー)を Java オブジェクトに変換してたものが渡される

–各メソッドに最大で1つのみ指定可能

–変換は、エンティティー・プロバイダーが行う

エンティティー・プロバイダー

– Java 型と表現 (representation) の間のマッピング・サービスを提供するプロバイダー

• MessageBodyReader

• MessageBodyWriter

22

@Path("employee") public class EmployeeResourceMgr { ・・・ @Path("{id:[A-Z][0-9]+}") @PUT public Response updateEmp( @PathParam("id") String empNo,

Employee emp ) {

// 指定された社員の情報を更新する } }

public class Employee ( private String name; private String ctryCode; private String deptCode; ・・・ getter/setter メソッド }

PUT /・・・/・・・/employee/E250 HTTP/1.1 Content-Type: application/json Accept: application/json ・・・・・・ Content-Length: xxx {"name":"jax ws","ctryCode":"jp","deptCode":"x15",……

HTTP リクエスト

エンティティー: メッセージ・ボディー(エンティティー・ボディー)に対応する Java オブジェクト

エンティティー プロバイダー

(MessageBodyReader)

Page 23: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

リソース・メソッドの戻り値の扱い

戻り値の型とエンティティー・ボディー&HTTPステータス・コードの関係

• 戻り値が null の時は、ステータス・コード 204 で、空のエンティティー・ボディーがクライアントに返される

• Response 型を使用すると、メタ・データを追加指定でき、最も柔軟な実装が可能となる

–エンティティー・プロバイダーが、Java オブジェクトをエンティティー・ボディーに変換する

23

戻り値の型 エンティティー・ボディー/HTTPステータス・コード

void 空

204 (No Content)

javax.ws.rs.core. Response

entity プロパティーに設定した内容

指定可

javax.ws.rs.core. GenericEntity

entity プロパティーに設定した内容

200 (OK)

その他の Java 型 該当の Java 型の内容

200 (OK)

@Path("employee") public class EmployeeResourceMgr { ・・・ @Path("{id:[A-Z][0-9]+}") @GET public Response queryEmp( … ) { // 指定された社員の情報を返す Employee emp = ……; … … … ResponseBuilder rb = Response.ok( emp ); return rb.build(); } @Path("{id:[A-Z][0-9]+}") @PUT public Response updateEmp( … ) { // 指定された社員の情報を更新する … … … return null; } }

Page 24: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

デフォルトのエンティティー・プロバイダー:全てのランタイムがサポートするもの

全てのランタイムで以下のマッピングがサポートされる

• JAXBElement およびアプリ提供の JAXB クラスの場合、アプリ提供のコンテキスト・リゾルバーが提供した JAXBContext が使用

される。(コンテキスト・プロバイダーの記載を参照)

• 応答を書き出す際には、アプリ指定の character set metadata が使用される。指定が無い場合は、UTF-8 が使用される。

24

Java の型 メディア・タイプ

byte[], java.lang.String, java.io.InputStream, java.io.Reader, java.io.File, javax.activation.DataSource

全てのメディア・タイプ (*/*)

javax.xml.transform.Source, javax.xml.bind.JAXBElement, アプリケーション提供の JAXB クラス

XML タイプ (text/xml, application/xml および application/*+xml)

MultivaluedMap<String,String> application/x-www-form-urlencoded

StreamingOutput 全てのメディア・タイプ (*/*) [MessageBodyWriter のみ]

java.lang.Boolean, boolean, java.lang.Character, char, java.lang.Number, int, short, long

text/plain

Page 25: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

デフォルトのエンティティー・プロバイダー:JSON-P が利用可能な環境での追加サポート (1)

JSON-P が利用可能な環境では、以下のマッピングがサポートされる

25

@Path("{id:[A-Z][0-9]+}") @GET public Response queryEmp( … ) { // 指定された社員の情報を返す … … … JsonObjectBuilder ob = Json.createObjectBuilder(); ob.add( "name", name ); ob.add( "ctryCode", ctry ); … … … JsonObject obj = ob.build(); return Response.ok( obj ).build(); }

@Path("{id:[A-Z][0-9]+}") @PUT public Response updateEmp( JsonObject obj ) { // 指定された社員の情報を更新する String name = obj.getString( "name" ); String ctry = obj.getString( "ctryCode" ); … … … return null; }

Java の型 メディア・タイプ

javax.json.JsonStructure, javax.json.JsonObject , javax.json.JsonArray

application/json

JSON-P: Java API for JSON Processing

リソース・メソッドでの利用例

Page 26: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

デフォルトのエンティティー・プロバイダー:JSON-P が利用可能な環境での追加サポート (2)

JSON-P が利用可能な環境では、JsonParser, JsonGenerator, JsonReader および JsonWriter

も利用できる • 全てのランタイムがサポートする InputStream, java.io.Reader および StreamingOutput を介して利用できる

26

@Provider @Produces( MediaType.APPLICATION_JSON ) public class EmpWriter implements MessageBodyWriter<Employee> { … … … @Override public void writeTo( …, OutputStream stream ) throws … { JsonObjectBuilder ob = Json.createObjectBuilder(); ob.add( "name", emp.getName() ); ob.add( "ctryCode", emp.getCtry() ); … … … JsonObject obj = ob.build(); JsonWriter jw = Json.createWriter( stream ); jw.write( obj ); jw.close(); return; } }

@Provider @Consumes( MediaType.APPLICATION_JSON ) public class EmpReader implements MessageBodyReader<Employee> { … … … @Override public Employee readFrom( …, InputStream stream ) throws … { JsonReader jr = Json.createReader( stream ); JsonObject obj = jr.readObject(); jr.close(); Employee emp= new Employee(); emp.setName( obj.getString( "name" ) ); emp.setCtry( obj.getString( "ctryCode" ) ); … … … return emp; } }

エンティティー・プロバイダーでの利用例

Page 27: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

クライアントへのエラー通知 / リソース・メソッドがスローした例外の扱い

クライアントへのエラー通知 は、HTTP のステータス・コードを使用する

–ステータス・コードを設定した Response オブジェクトを返す

–ステータス・コードを設定した javax.ws.rs.WebApplicationException (および、サブクラス)をスローする

–例外マッピング・プロバイダーを使用して、ステータス・コードを設定した Response にマップする

リソース・メソッドがスローした例外の扱い

–例外 javax.ws.rs.WebApplicationException (および、サブクラス)

• Response にエンティティーが設定されておらず、対応する例外マッピング・プロバイダーが存在する場合は、例外マッピング・プロバイダーが例外を Response にマッピングする

• その他の場合は、例外に設定したステータス・コードとエンティティーがクライアントに通知される (設定していない場合は、ステータス・コード 500 で、空のレスポンスが通知される)

–その他の例外

• 対応する例外マッピング・プロバイダーが存在する場合は、例外マッピング・プロバイダーが例外を Response にマッピングする

• 存在しない場合は、実装コンテナーに通知される

例外マッピング・プロバイダーの詳細は、「プロバイダー」の章を参照

27

Page 28: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

メディア・タイプ

リクエストとレスポンスのメディア・タイプを宣言 • リソース・クラスとリソース・メソッドに対してアノテーションを付与することで宣言

(リソース・メソッドでの宣言が優先される)

• 宣言しないと、全てのメディア・タイプ(*/*)をサポートすると想定される

–@javax.ws.rs.Consumes

• 受け入れることが可能なメディア・タイプを宣言

• HTTP リクエストの "Content-Type" ヘッダーのメディア・タイプとマッチング

–@javax.ws.rs.Produces

• 生成できるメディア・タイプを宣言

• HTTP リクエストの "Accept" ヘッダーのメディア・タイプとマッチング

–複数のメディア・タイプに対応する場合は併記する

• 例:@Produces( { "application/json", "text/xml" } )

–HTTP リクエストとメディア・タイプがマッチするメソッドが呼び出される

• マッチするメソッドがない場合は、エラーとなる

– @Consumesがマッチしない: 415 (Unsupported Media Type)

– @Produces がマッチしない: 406 (Not Acceptable)

28

@Path("employee") @Consumes( MediaType.APPLICATION_JSON ) @Produces( MediaType.APPLICATION_JSON ) public class EmployeeResourceMgr {

@Path("{id:[A-Z][0-9]+}") @PUT public Response updateEmp( … ) { … … … } @Path("{id:[A-Z][0-9]+}") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.TEXT_PLAIN) @PUT public Response updateEmpByForm( … ) { … … … }

}

PUT /・・・/・・・/employee/E200 HTTP/1.1 Content-Type: application/json Accept: application/json

{"name":"Jhon","ctryCode":…… } リクエスト

PUT /・・・/・・・/employee/E220 HTTP/1.1 Content-Type: application/x-www-form-urlencoded Accept: text/plain

name=Bob&ctryCode=…… リクエスト

Page 29: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

JAXB クラスの利用(XML と JSON のマルチメディア対応)

エンティティーとして JAXB クラスを使用すると…

–XML 形式のデータが簡単に扱える

• POJO に JAXB アノテーション (javax.xml.bind.annotationパッケージ)を付与するだけ

– JSON 形式のデータも簡単に扱える

• XML と JSON のマルチ・メディアに対応できる

• JSON データの形式もカスタマイズできる

29

@XmlRootElement(name="emp") public class Employee ( private String name; private String ctry; … … … @XmlElement(name="ctryCode") public String getCtry() { return ctry; } … … … }

JAXB: Java Architecture for XML Binding

@Path("employee") @Consumes( { MediaType.APPLICATION_JSON, MediaType.TEXT_XML } ) @Produces( { MediaType.APPLICATION_JSON, MediaType.TEXT_XML } ) public class EmployeeResourceMgr { @Path("{id:[A-Z][0-9]+}") @GET public Response queryEmp( … ) { // 指定された社員の情報を返す Employee emp = ……; … … … return Response.ok( emp ).build(); } }

<?xml …?><emp><name>Jhon</name><ctryCode>jp</…

GET /・・・/・・・/employee/E200 HTTP/1.1 Accept: text/xml

{"name":"Jhon","ctryCode":"jp", ……

GET /・・・/・・・/employee/E200 HTTP/1.1 Accept: application/json

Page 30: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

Range Requests

照会結果が多い場合の問題と対応

–問題:全件を返すのは現実的ではない。クライアントが全件を使用しないなら無駄になる。など。

–対応:クライアントが要求した(必要そうな)範囲のデータだけ返す。追加で必要な場合は、残りを要求してもらう。

HTTP では、Range Requests の仕様で対応

–HTTP リクエストの "Range" ヘッダー

• 必要とする検索結果の範囲を指定するためにクライアントがセット

• 形式: Range: (範囲単位)=(範囲の始め)-(範囲の終わり)

• 例: Range: items=0-24 ---- 0番目から24番目までを要求

–HTTP レスポンスの "Content-Range" ヘッダー

• 応答として返した範囲と総件数を通知するためにサービスがセット

• 形式: Content-Range: (範囲単位) (範囲の始め)-(範囲の終わり)/(総件数)

• 例: Content-Range: items 0-24/66 ---- 全66件中、0番目から24番目を返却

–範囲単位

• HTTP の Range Requests で定義されている単位は bytes のみ

• 上記例の items は dojo toolkit の JsonRest ストアで使用されている単位

30

Page 31: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

Bean Validation の使用

Bean Validation 仕様に沿った declarative validation が使用可能

–リソース・クラスのフィールドやプロパティー

–リソース・メソッドのパラメーター

–エンティティー

• リソース・メソッドの戻り値

• リソース・メソッドのパラメーター

カスタム実装のバリデーションもサポート

バリデーション・エラーになると、以下の応答が返る

–500 (Internal Server Error)

–400 (Bad Request)

31

@Path("employee") public class EmployeeResourceMgr { ・・・ @GET public Response list( @NotNull @QueryParam("country") String cntry ){ // 条件に一致する社員の情報を返す } @Path("{id:[A-Z][0-9]+}") @GET @Valid public Response queryEmp( @PathParam("id") String empNo ) { // 指定された社員の情報を返す Empoyee emp = …; return Response.ok( emp ).build(); } @Path("{id:[A-Z][0-9]+}") @PUT public Response updateEmp( @PathParam("id") String empNo, @Valid Employee emp ) { // 指定された社員の情報を更新する } ・・・ }

public class Employee ( @NotNull private String name; @NotNull private String ctryCode; @NotNull private String deptCode; ・・・ getter/setter メソッド }

Page 32: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

補足:HTTPメソッドの選択

HTTP メソッドの意味と特徴

• 安全 リソースの状態に変更を加えないということ

• べき等 複数回同一のリクエストを行った場合に、1回目と2回目のリクエストの後でリソースの状態に相違がないということ

PUT と POST による追加操作の相違

–PUT: 新規リソースの URI をクライアントが割り当てられる場合(知っている場合)に使用

–POST: 新規リソースの URI が追加時に確定し、追加完了後にクライアントに通知される場合に使用

すでに定義されている限られた HTTP メソッドを目的にそって使用

32

HTTP メソッド 意味 持つべき特徴

安全(Safe) べき等(Idempotent)

GET リソースの取得 ○ ○

PUT リソースの更新、または、追加 ○

POST リソースの追加

DELETE リソースの削除 ○

Page 33: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

補足:WebApplicationException のサブクラスと HTTP ステータス・コード

33

例外クラス 概要 コード

java.lang.RuntimeException

javax.ws.rs.WebApplicationException

javax.ws.rs.RedirectionException リダイレクト・レスポンスを示す例外 30x

javax.ws.rs.ClientErrorException クライアント・リクエスト・エラーを示す例外 4xx

javax.ws.rs.BadRequestException 不正リクエストを示す例外 400

javax.ws.rs.NotAuthorizedException 認証エラーを示す例外 401

javax.ws.rs.ForbiddenException アクセス拒否を示す例外 403

javax.ws.rs.NotFoundException リソースが見つからないことを示す例外 404

javax.ws.rs.NotAllowedException 要求メソッドの不許可を示す例外 405

javax.ws.rs.NotAcceptableException 受付不可を示す例外 406

javax.ws.rs.NotSupportedException 未サポートのメディア・タイプを示す例外 415

javax.ws.rs.ServerErrorException サーバー・エラーを示す例外 5xx

javax.ws.rs.InternalServerErrorException サーバーの内部エラーを示す例外 500

javax.ws.rs.ServiceUnavailableException 過負荷などによるサービス利用不可を示す例外

503

Page 34: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

34

補足:HTTP ステータス・コード: 正常系(1xx系と2xx系)

コード 意味 補足

1xx Informational 情報

2xx Successful 成功

200 OK リクエスト成功

応答データが存在する場合のデフォルトのステータス・コード

201 Created リソースが生成された

202 Accepted 受け付けられたが、処理は完了していない

204 No Content 成功したが、応答するデータが無い

応答データが無い場合のデフォルトのステータス・コード

206 Partial Content Range Requests によりコンテンツの一部を応答した

3xx Redirection リダイレクト

301 Moved Permanently 恒久的なリダイレクト

302 Found リソースが一時的に移動されていることをあらわす

303 See Other 他の URI の参照を促す

304 Not Modified クライアントのキャッシュが最新であることをあらわす

307 Temporary Redirect 一時的なリダイレクト

Page 35: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

35

補足:HTTP ステータス・コード: 異常系(4xx系)

コード 意味 補足

4xx Client error クライアント・エラー

400 Bad Request 不正リクエスト

ランタイムが HeaderParam, CookieParam のインジェクションができなかった場合に応答

401 Unauthorized 認証エラー

403 Forbidden アクセス拒否

404 Not Found

リソースが見つからない

ランタイムが要求 URI にマッチするリソース・メソッドを見つけられなかった場合や、PathParam, QueryParam, MatrixParam のインジェクションができなかった場合に応答

405 Method Not Allowed 要求メソッドの不許可

ランタイムが要求 HTTP メソッドにマッチするリソース・メソッドを見つけられなかった場合に応答

406 Not Acceptable

受付不可 (クライアントが受け付け可能な応答データを生成できない)

ランタイムがクライアントが期待する応答コンテントのメディア・タイプにマッチする @Produces アノテーションのリソース・メソッドを見つけられなかった場合に応答

409 Conflict リソースの状態との競合により、処理を完了できない

410 Gone 要求されたリソースがすでに削除されている

412 Precondition Failed 前提条件をみたさない

415 Unsupported Media Type

未サポート・メディア・タイプ

ランタイムが要求コンテントのメディア・タイプにマッチする @Consumes アノテーションのリソース・メソッドを見つけられなかった場合に応答

Page 36: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

36

補足:HTTP ステータス・コード: 異常系(5xx系)

コード 意味 補足

5xx Server error サーバー・エラー

500 Internal Server Error サーバーの内部エラー

リソース・メソッドからステータス・コード指定なしの WebApplicationException がスローされた場合のステータス・コード

503 Service Unavailable 過負荷などによりサービス利用不可

Page 37: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

4. JAX-RS クライアントの開発

Page 38: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

JAX-RS クライアント:概要

JAX-RS 2.0 から JAX-RS クライアントの機能を提供

– javax.ws.rs.client パッケージ

以下のステップで REST サービスを呼び出せる • (1) Client のインスタンスを取得

• (2) WebTarget を作成

• (3) リクエストを生成

• (4) サービスを呼び出す (リクエストを実行/サブミットする)

メソッド呼び出しを繋げることで、準備から実装までが行える -- "fluent API"

38

Client client = ClientBuilder.newClient(); Response res = client.target( "http://www.example.org/contextRoot/appPath/employee" ) .queryParam( "country", "jp" ) .request( "application/json" ) .header( "Range", "items=0-24" ) .get();

Client client = ClientBuilder.newClient(); WebTarget wt = client.target( "http://host/cr/ap/employee/E250" ); Response res = wt.request( "application/json" ).get();

Page 39: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

JAX-RS クライアント:エンティティーの操作

レスポンスからのエンティティーの取得

– javax.ws.rs.core.Response オブジェクト

• エンティティーは readEntity() メソッドで取得

• ヘッダー情報なども取得できるので最も柔軟な方法

–エンティティー・プロバイダーが対応する Java 型

リクエストへのエンティティーの設定

– javax.ws.rs.client.Entity を使用して設定

39

Client client = ClientBuilder.newClient(); Employee emp = client.target( "http://…/employee/E250" ) .request( MediaType.APPLICATION_JSON ) .get( EmpData.class );

Employee emp = …… Client client = ClientBuilder.newClient(); WebTarget wt = client.target( "http://…/employee/E300" ); Response res = wt.request( "application/json" ) .put( Entity.entity( emp, MediaType.APPLICATION_JSON ) );

Client client = ClientBuilder.newClient(); List<Employee> l = client.target( "http://…/employee" ) .request( MediaType.APPLICATION_JSON ) .get( new GenericType<List<EmpData>>(){} );

Client client = ClientBuilder.newClient(); Response res = client.target( "http://…/employee/E220" ) .request( MediaType.APPLICATION_JSON ) .get();

•List などの場合は、javax.ws.rs.core.GenericType で指定

エンティティー: メッセージ・ボディー(エンティティー・ボディー)に対応する Java オブジェクト

Page 40: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

JAX-RS クライアント:WebTarget

WebTarget を使用すると、複雑な URI が簡単に作成できる

–ベース URI の作成

–パスの追加

–テンプレートの使用

WebTarget の特徴

–パス追加やテンプレート解決を行っても変更されない

• 新しい WebTarget のインスタンスが作成され、元のインスタンスへ変更されない

–但し、構成の変更は該当のインスタンスに対して適用される

40

WebTarget base = client.target( "http://www.example.org/contextRoot/appPath/" ); WebTarget qEmp = base.path( "employee" ).path( "{id}" ); WebTarget qE63 = qEmp.resolveTemplate( "id", "E63" ); Response res = qE63.request( "application/json" ).get();

WebTarget qE63 = qEmp.resolveTemplate( "id", "E63" ); qE63.register( MyProvider1.class ).register( MyProvider2.class ); Response res = qE63.request( "application/json" ).get();

•base, qEmp, qE63 は別インスタンスを参照

• register() が返すのは同じインスタンス

Page 41: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

JAX-RS クライアント:Invocation

Invocation は、準備済みで実行可能なリクエスト

invoke / submit で実行

– invoke() 同期呼び出し

– submit() 非同期呼び出し

41

Employee emp = new Employee(); emp.setName( "" ); … Client client = ClientBuilder.newClient(); WebTarget wt = client.target( "http://host/cr/ap/employee/E400" ); Invocation iv = wt.request( "application/json" ).buildPut( Entity.entity( emp, "application/json" ) );

Response res = iv.invoke();

Page 42: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

5. 非同期処理

Page 43: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

サーバー側の非同期処理

非同期の意味

–別スレッドが処理を行い、準備ができた時点でレスポンスが返される

• リソース・メソッドが終了する時点ではレスポンスを返さない

–通信としては同期のままなので、クライアントから見た場合は同期でも非同期でも差異はない

以下の2つの実装が可能

–Concurrency Utilities for Java EE を使用した実装

• リソース・クラスの実装が POJO の場合

–EJB の非同期メソッドを使用した実装

• リソース・クラスの実施が Stateless および Singleton の Session Bean の場合

タイムアウト発生時の通知機能をサポート

43

Page 44: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

サーバー側の非同期処理: 実装(1)

非同期処理を行うリソース・メソッド

–パラメーターとして @Suspended アノテーションを付与した AsyncResponse を持つ

–メソッドの戻りは void 型

応答

–AsyncResponse の resume() メソッドで生成

タイムアウト

–AsyncResponse に対してタイムアウト値を設定

–タイムアウト時に実行されるハンドラーを指定可能

• 設定しないと、ステータスが 503 の ServiceUnavailableException が生成される

44

@Resource(lookup="……") ManagedExecutorService executor; @GET public void longRunningOp( @Suspended final AsyncResponse ar ) {

ar.setTimeoutHandler( new TimeoutHandler() { public void handleTimeout( AsyncResponse ar ) { ar.resume( Response.status( SERVICE_UNAVAILABLE ) .entity( "Operation timed.") .build() ); } }); ar.setTimeout( 15, java.util.concurrent.TimeUnit.SECONDS ); executor.execute( new Runnable() { public void run() { executeLongRunningOp(); ar.resume("Hello async world!"); } } );

} •別スレッドで処理を行う •レスポンスは AsyncResponse の resume() で返す

•AsyncResponse に対して、タイムアウト・ハンドラーとタイムアウト値を設定

Page 45: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

サーバー側の非同期処理: 実装(2)

リソース・クラスが EJB の場合

–EJB コンテナーがメソッドを非同期に呼び出すので、明示的なスレッド操作は不要

非同期処理を行うリソース・メソッド

–EJB の @Asynchronous アノテーションを付与

–パラメーターとして @Suspended アノテーションを付与した AsyncResponse を持つ

–メソッドの戻りは void 型

応答

–AsyncResponse の resume() メソッドで生成

タイムアウトは設定できない

45

@Stateless @Path("longRunning") class EJBResource { @GET @Asynchronous public void longRunningOp( @Suspended AsyncResponse ar ) { executeLongRunningOp(); ar.resume("Hello async world!"); } }

Page 46: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

クライアント側の非同期処理

非同期の意味

–別スレッドでサービスを呼び出す

–通信としては同期のまま

非同期処理の開始

–async() を間に挟んで実行するか、

– Invocation を生成して submit() を実行

結果の取得

–呼び出し時に InvocationCallback を指定することで取得

–開始時に戻された java.util.concurrent.Future<T> 型のオブジェクトから取得

46

Client client = ClientBuilder.newClient(); WebTarget wt = client.target("http://……"); wt.request( "application/json" ) .async() .get( new InvocationCallback<Customer>() { @Override public void completed( Customer customer ) { // Do something } @Override public void failed( Throwable throwable ) { // Process error } } );

•レスポンスが返ると InvocationCallback の completed() が呼び出される

Client client = ClientBuilder.newClient(); WebTarget wt = client.target("http://……"); Future<Customer> f = wt.request( "application/json" ) .get( Customer.class ); ・・・・・・・・・ Customer c = f.get(); • isDone() で完了済みか確認し、

get() で結果を取得

Page 47: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

6. プロバイダーの開発

Page 48: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

プロバイダーの概要

プロバイダーの種類

–主要なプロバイダ

• エンティティー・プロバイダー

• コンテキスト・プロバイダー

• 例外マッピング・プロバイダー

–インターセプターとフィルター

• エンティティー・インターセプター

• フィルター

–その他

• パラメーター・コンバーター・プロバイダー

ライフサイクル

–プロバイダーのインスタンスは JAX-RS アプリケーション毎に1つ作成される

• プロバイダーは繰り返し使用され、マルチスレッドから同時に呼び出される

自動検出

–@Provider アノテーションを付与することで、プロバイダーとして自動的に検出される

48

Page 49: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

エンティティー・プロバイダー

Java 型と表現 (representation) の間のマッピング・サービスを提供

MessageBodyReader

–表現 (representation) から Java 型への変換サービスを提供

–インターフェース javax.ws.rs.ext.MessageBodyReader<T> を実装

• boolean isReadable(…) マッピングできるか否かを返す

• T readFrom(…) マッピングを行う

–@Provider を付与

–@Consumes でサポートするメディア・タイプを指定

MessageBodyWriter

– Java 型から表現 (representation) への変換サービスを提供

–インターフェース javax.ws.rs.ext.MessageBodyWriter<T> を実装

• boolean isWriteable(…) マッピングできるか否かを返す

• long getSize (…) ゼロを返す (JAX-RS 2.0 で deprecated)

• void writeTo(…) マッピングを行う

–@Provider を付与

–@Produces でサポートするメディア・タイプを指定

49

Page 50: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

コンテキスト・プロバイダー

リソース・クラスや他のプロバイダーにコンテキストを提供

–インターフェース javax.ws.rs.ext.ContextResolver<T> を実装

• T getContext( Class<?> type) 対応するコンテキストを返す

–@Provider を付与

–@Produces でサポートするメディア・タイプを指定

カスタムの JAXBContext を使用したい場合であれば、ContextResolver<JAXBContext> を実装

50

Page 51: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

例外マッピング・プロバイダー

リソース・クラスやプロバイダーで発生した例外を Response にマッピング機能を提供

– javax.ws.rs.ext.ExceptionMapper<E> を実装

• Response toResponse( E ) マッピングを行う

–@Provider を付与

JAX-RS アプリケーション(Server Runtime)でのみ使用でき、 JAX-RS クライアントでは使用できない

51

Page 52: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

エンティティー・インターセプター

特定の拡張ポイントにおいてメソッド呼び出しをラップ

–拡張ポイント毎のチェインに組み込まれ、プライオリティー順に呼び出される

–コンテキスト・オブジェクトの proceed(…) を必ず呼び出し、処理を進める

2つのインターセプターを規定

MessageBodyReader の readFrom(…) をラップするもの

– javax.ws.rs.ext.ReaderInterceptor インターフェースを実装

• aroundReadFrom( ReaderInterceptorContext context )

–@Provider を付与

MessageBodyWriter の writeTo(…) をラップするもの

– javax.ws.rs.ext.WriterInterceptor インターフェースを実装

• aroundWriteTo( WriterInterceptorContext context )

–@Provider を付与

用途の例

–リクエストを zip 解凍し、レスポンスを zip 圧縮する

52

Page 53: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

フィルター

拡張ポイントで処理を行う

–拡張ポイント毎のチェインに組み込まれ、プライオリティー順に呼び出される

5(=4+1)つの拡張ポイントがある

ClientRequest (クライアント側) と ContainerRequest (サーバー側)

–サービスへ送信するリクエストや、クライアントから着信したリクエストを加工するポイント

–コンテキスト・オブジェクトの abortWith(Response) を呼び出すことで後続の処理を中止できる。abortWith() に渡した Response がレスポンスとして使用される

• 用途例:キャッシュ機能の実現 (キャッシュからレスポンスを返す)

ClientResponse (クライアント側) と ContainerResponse (サーバー側)

–サービスから着信したレスポンスや、クライアントへ送信するレスポンスを加工するポイント

• 用途例:キャッシュ機能の実現 (レスポンスをキャッシュに取り込む)

PreMatchContainerRequest (サーバー側)

–クライアントから着信したリクエストを加工するポイント

–マッチングが行われる前の段階で呼び出されるので、マッチング動作を変更できる

• 用途例:X-HTTP-Method-Override ヘッダー付きで送られてきた POST 要求を、ヘッダーで指定されたメソッドに置き換える

53

Page 54: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

フィルターの実装

拡張ポイントに対応したインターフェースを実装 • ClientRequest javax.ws.rs.ext.ClientRequestFilter

• ContainerRequest javax.ws.rs.ext.ContainerRequestFilter

• PreMatchContainerRequest 〃

• ClientResponse javax.ws.rs.ext.ClientResponseFilter

• ContainerResponse javax.ws.rs.ext.ContainerResponseFilter

– filter(…) メソッド

• リクエスト系のフィルター リクエスト・コンテキストが渡される

• レスポンス系のフィルター リクエスト・コンテキストとレスポンス・コンテキストが渡される

アノテーションを付与

–@Provider を付与

–拡張ポイントが PreMatchContainerRequest の場合は、更に、@PreMatching を付与

54

Page 55: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

エンティティー・インターセプターとフィルターのバインド

JAX-RS アプリケーション(Server Runtime)

–Global Binding

• 全てのリソース・メソッドにバインド

• デフォルトのバインディング方法 (Name Binding 用のアノテーションが付与されていない、エンティティー・インターセプターやフィルターの場合)

–Name Binding

• @NameBinding メタ・アノテーションを使用してバインディング用のアノテーションを定義

• 定義したアノテーションをリソース・メソッド、リソース・クラス、アプリケーションに付与することでバインド

–Dynamic Binding

• DynamicFeature を実装したフィーチャー(プロバイダーの一種)を使用して、動的にバインド

JAX-RS クライアント

–Client や WebTarget の register(…) メソッドでバインド

55

Page 56: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

7. まとめ

Page 57: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

まとめ

当ガイドでは Java EE 7 アプリケーション設計ガイドとして、JAX-RS 2.0 について解説を行いました

• RESTful Web サービスがアノテーションを使用して簡単に開発できます

• リソース・クラス、Application サブクラス

• JAX-RS クライアントの機能が追加されました

• javax.ws.rs.client パッケージ

• 非同期処理も使用できるようになりました

• サーバー側とクライアント側の両方で使用できます

• 各種プロバイダーを実装すると、ランタイムの機能を強化・補完できます

• エンティティー・プロバイダー、例外マッピング・プロバイダー、……

• 新たに、エンティティー・インターセプターとフィルターが追加されました

JAX-RS 2.0

57

Page 58: Java EE 7 アプリケーション設計ガイドpublic.dhe.ibm.com/.../JavaEE7AppGuide_JAXRS.pdfJava EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編 javax.ws.rs.core.Application

© 2015 IBM Corporation

Java EE 7 アプリケーション設計ガイド - JAX-RS 2.0 編

参考資料

JSR 339: JAX-RS 2.0: The Java API for RESTful Web Services – https://jcp.org/en/jsr/detail?id=339

JavaTM EE 7 Specification APIs – http://docs.oracle.com/javaee/7/api/

The Java EE 7 Tutorial – http://docs.oracle.com/javaee/7/tutorial/index.html

IBM Knowledge Center - WebSphere Application Server Liberty Core 8.5.5 – http://www-01.ibm.com/support/knowledgecenter/SSD28V/welcome

WebSphere Application Server V8 アナウンスメント・ワークショップ資料 – http://www.ibm.com/developerworks/jp/websphere/library/was/was8_ws/

Liberty Profile Beta – https://developer.ibm.com/wasdev/

58