beginning java ee 6 勉強会(7) #bje_study

38
Beginning Java EE 6 勉強会(7) -RESTful Webサービス(JAX-RS)- 担当者:ikeyat 2012/07/04

Upload: ikeyat

Post on 31-May-2015

5.546 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Beginning Java EE 6 勉強会(7) #bje_study

Beginning Java EE 6 勉強会(7)-RESTful Webサービス(JAX-RS)-

担当者:ikeyat

2012/07/04

Page 2: Beginning Java EE 6 勉強会(7) #bje_study

アンケート

• REST知ってますか?

– 知らない

– 聞いたことがある

– 使ったことがある

– 人に説明することができる

2

Page 3: Beginning Java EE 6 勉強会(7) #bje_study

INDEX

● REST

● JAX-RS

3

Page 4: Beginning Java EE 6 勉強会(7) #bje_study

REST

Page 5: Beginning Java EE 6 勉強会(7) #bje_study

RESTとは

● Webサービスのアーキテクチャスタイルの一つ– 仕様や実装ではない

– もちろんプロトコルでもない(SOAPはプロトコル)

● 二つの意味で使用されている– HTTPを用いた簡易的なRPC

– Roy Fieldingが提唱するWebサービスアーキテクチャスタイル

5

Page 6: Beginning Java EE 6 勉強会(7) #bje_study

RESTとは

● HTTPを用いた簡易的なRPC– クライアントはサービスを呼び出すために、手続きに対しHTTPリク

エストする(例:検索、追加)

– URIに動詞が含まれることが多い(例:deleteXxx)

– GETやPOSTが用いられることが多い

– 例:Amazon API

6

GEThttp://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=[AWS アクセスキー ID]&AssociateTag=[Associate Tag]&Operation=CartClear&CartId=[Cart ID]&HMAC=[URL-encoded HMAC]

Page 7: Beginning Java EE 6 勉強会(7) #bje_study

RESTとは

● Roy Fieldingが提唱するWebサービスアーキテクチャスタイル– クライアントはサービスを呼び出すために、リソースに対しHTTPリ

クエストする(例:本、カテゴリ)

– URIは名詞である(例:book、books、categories)

– リソースに対する手続きの種類はCRUDで、HTTPのメソッドで指定する(GET/POST/PUT/DELETE)

– 本書ではこちらに従う

7

DELETEhttp://www.apress.com/books/1023

Page 8: Beginning Java EE 6 勉強会(7) #bje_study

RESTとは

● Roy Fielding式RESTを学ぶ上で必要な知識=Web– リソースとURI

– 表現

– HTTP

● メソッド● コンテンツ・ネゴシエーション● ステータスコード● キャッシュ

8

Page 9: Beginning Java EE 6 勉強会(7) #bje_study

Web● リソース

– 参照もしくは操作の対象となるサーバ上のオブジェクト。

– 例:

● Apress社のJavaに関する書籍のリスト

● 書籍『The Definitive Guide to Grails』

● Ola Biniの経歴

● URI– Web上のリソースを特定する識別子。内容が分かるような文字列にするとよい。

– 例:

● http://www.apress.com/book/catalog

● http://www.weather.com/weather/2008?location=Paris

● http://www.flickr.com/explore/interesting/2009/01/01

9

Page 10: Beginning Java EE 6 勉強会(7) #bje_study

Web

● 表現– リソースをクライアントで扱う際の形式。

● 例:テキスト、HTML、XML、JSON、JPG画像、PDF

– 必要に応じて、一つのリソースに対し複数の表現を用意することもある。

● 例:書籍一覧のHTML、書籍一覧CSV

– クライアントが表現を選択する方法

● URIを拡張子などで分ける方法

– http://xxxxxx/xxx/books.html– http://xxxxxx/xxx/books.csv

● コンテンツ・ネゴシエーションを使用する方法(後述)

10

Page 11: Beginning Java EE 6 勉強会(7) #bje_study

Web

● HTTP

11

GET /book/catalog?category=32 HTTP/1.1User-Agent: xxxxxxHost: www.apress.comAccept: */*

<GETの場合は空>

HTTP/1.1 200 OKDate: Mon, 23 Feb 2009 07:28:09 GMTServer: Apache/2.0.63 (Unix) PHP/5.2.6Set-Cookie: XX=YYYYYYExpires: Thu, 19 Nov 1981 08:52:00 GMTCache-Control: no-store, no-cache, …Pragma: no-cacheTransfer-Encoding: chunkedContent-Type: text/html

<!DOCTYPE HTML><html> <head> <title> <body>...

リクエスト例 レスポンス例

Page 12: Beginning Java EE 6 勉強会(7) #bje_study

Web

● HTTP

12

GET /book/catalog?category=32 HTTP/1.1User-Agent: xxxxxxHost: www.apress.comAccept: */*

<GETの場合は空>

HTTP/1.1 200 OKDate: Mon, 23 Feb 2009 07:28:09 GMTServer: Apache/2.0.63 (Unix) PHP/5.2.6Set-Cookie: XX=YYYYYYExpires: Thu, 19 Nov 1981 08:52:00 GMTCache-Control: no-store, no-cache, …Pragma: no-cacheTransfer-Encoding: chunkedContent-Type: text/html

<!DOCTYPE HTML><html> <head> <title> <body>...

リクエスト例 レスポンス例メソッドステータスコード

コンテンツネゴシエーション

Page 13: Beginning Java EE 6 勉強会(7) #bje_study

Web

● メソッド– リソースに対する操作の種類。主にGET/POST/PUT/DELETEを

用いる。

13

メソッド CRUD リソース変化 HTTP本体

GET R なし なし リソースの返却を要求する

POST C あり あり リソースの新規作成を要求する

PUT U あり あり リソースの更新を要求する

DELETE D あり なし リソースの削除を要求する

他にもHEAD/TRACE/OPTIONS/CONNECTがあります

Page 14: Beginning Java EE 6 勉強会(7) #bje_study

Web

● コンテンツ・ネゴシエーション– 使用可能な「表現」が複数存在する時に、最適な表現を選択する

プロセス。

– クライアントはHTTPリクエストヘッダで要求する表現を指定できる。サーバはこれに応じた表現を返却するのが望ましい。

● Accept:コンテンツ・タイプ● Accept-Charset:文字コード● Accept-Encoding:エンコード● Accept-Language:言語

14

Page 15: Beginning Java EE 6 勉強会(7) #bje_study

Web

● コンテンツ・タイプ– text/html

– text/plain

– image/gif, image/jpeg, image/png

– text/xml, application/xml

– application/json

15

Page 16: Beginning Java EE 6 勉強会(7) #bje_study

Web

● ステータスコード– 1xx:情報を示す。リクエストを受信しプロセスを継続。

– 2xx:処理の精巧を示す。リクエストを正しく受信し、理解。

● 200 OK

– 3xx:リダイレクトを示す。リクエストを完了するために更なる操作が必要。

● 301 Moved Permanently

– 4xx:クライアントエラーを示す。リクエストに不適切な構文が含まれる、もしくはリクエストを満たすことができない。

● 404 Not Found

– 5xx:サーバーエラーを示す。サーバーは有効なリクエストに対し実行できない。

● 500 Internal Server Error

16

Page 17: Beginning Java EE 6 勉強会(7) #bje_study

RESTとは

● (話戻って)RESTアーキテクチャスタイルとは– 統一インタフェース

● HTTP(GET/POST/PUT/DELETEおよびステータスコード)に準拠する(=URIさえ分かれば利用できる)

– アドレス指定

● アプリケーションが扱う情報をアドレス(URI)で指定できるようにする

– 連結性

● 関連するリソース同士をURIでリンクさせる

● 例:CDリソースの中にアーティスト情報がある場合、その名前だけでなくURIも含める

– ステートレス

● リソースの状態はサーバで管理

● アプリケーションの状態はクライアントで管理

17

Page 18: Beginning Java EE 6 勉強会(7) #bje_study

RESTとは

● 連結性の例

18

<cd> <title>Ella and Louis</title> <year ref=”http://music.com/year/1956”>1956</year> <artist ref=”http://music.com/artists/123”>Ella Fitzgerald</artist> <artist ref=”http://music.com/artists/456”>Louis Armstrong</artist> <link rel=”self” type=”text/json” href=”http://music.com/album/789” /> <link rel=”self” type=”text/xml” href=”http://music.com/album/789” /> <link rel=”http://music.com/album/comments” type=”text/xml” href=”http://music.com/album/789/comments” /></cd>

Page 19: Beginning Java EE 6 勉強会(7) #bje_study

RESTとは

● メリット– クライアントとサービスの結びつきが弱い

– スケーラビリティ性

● ステートレス● HTTPキャッシュ● コンパクトな電文(JSON)

– 1HTTPリクエストで簡潔(SOAPはWSDL取るので2リクエスト)

● デメリット– 透過的に扱えない

– プロトコルがHTTPに限定

– SOAPにあるようなWS-*(WS-Security,etc...)標準が無い

19

Page 20: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RS

Page 21: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RS

● JAX-RS1.1– JavaでRESTfulなWebサービスを開発するためのAPI仕様

– JavaEE6に導入

– アノテーションを利用

● ローカルBeanインタフェースもしくはインタフェースなしBeanに適用可能

– サーバサイドのみ

– 永続性マネージャ、データソース、EJBなどのDI可能

● 実装– Jersey (Sun) : GlassFish3に搭載

– Apache CXF

– RESTeasy (JBoss)

21

Page 22: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RS

● (参考)JAX-RS2.0(JavaEE7)– クライアントAPI

– FiltersとHandlers

– BeanValidationを用いたパラメータの検証機能

– 非同期処理(クライアント側でFutureオブジェクトを返す)

– 優れた接続ネゴシエーション

22https://blogs.oracle.com/arungupta/entry/jax_rs_2_0_earlyより

Page 23: Beginning Java EE 6 勉強会(7) #bje_study

Java EE 6の全体像

23

http://www.slideshare.net/takakiyo/jjuc-ccc-2010-spring より拝借

Page 24: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RS

● JAX-RSモデル– リソースを表すPOJOクラスに@javax.ws.rs.Pathアノテーションを付加。

– リソースクラスのメソッドに@GET/@POST/@PUT/@DELETEアノテーションを付加し、各操作の処理を記述する。

– EJB機能を利用する場合はステートレスセッションBeanに@Pathを付加。

24

@Path(“/book”)public class BookResource { @GET @Produces(“text/plain”) public String getBookTitle() { return “H2G2”; }}

www.apress.com

GET http://www.apress.com/book

200 OKH2G2

Page 25: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● URI定義– @Pathでコンテキストルートからの相対パスを指定。

– クラスに付加した@PathのURIはルートリソース

● 例:/items

– ルートリソースのメソッドに@Pathを付加し、小リソースの操作を記述することも可能。

● 例:/items/books

– URI構文に変数を埋め込むことも可能。@PathParamで参照。

● 例:/items/{itemid}

25

@Path(“/items”)public class ItemResource { @GET public List<Item> get...() {...}

@GET @Path(“/{itemid}”) public Item get...( @PathParam(“itemid”) String itemid) {...}}

GET /items

GET /items/1234

Page 26: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● パラメータの抽出

26

アノテーション 取得元 説明 例

@PathParam URI @Pathで指定したURIテンプレートパラメータ

@PathParam(“itemId”)

@QueryParam URI URIクエリパラメータ(?以降のxxx=yyy)

@QueryParam(“zip”)

@MatrixParam URI URIの;で区切られたパラメータ(.../books;author=hoge)

@MatrixParam(“author”)

@CookieParam Cookie Cookieの値 @CookieParam(“sessionid”)

@HeaderParam HTTPヘッダ

リクエストHTTPヘッダの値 @HeaderParam(“Content-Type”)

@FormParam リクエスト本文

HTMLフォームからのパラメータ @FormParam(“password”)

@DefaultValue(“デフォルト値”)でデフォルト値の設定が可能

Page 27: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● コンテンツタイプの使用と生成– リクエストのコンテンツタイプに応じて呼び出すメソッドを振り分け

る→@Consumes

– リクエストのAcceptに応じて呼び出すメソッドを振り分ける→@Produces

27

@Path(“/items”)@Produces(MediaType.TEXT_PLAIN)public class CustomerResource { @GET public String getAsPlainText() {...}

@GET @Produces(MediaType.TEXT_HTML) public String getAsHtml() {...}

@GET @Produces(MediaType.Application_JSON) public List<Customer> getAsJson() {…}

@PUT @Consumes(MediaType.Application_XML) public Response createCustomer(InputStream is) {...}

}

Accept: text/plain

Content-Type: application/xml

Accept: text/html

Accept: application/json

Page 28: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● エンティティプロバイダ– HTTP本体(JSONやXML等)をJavaオブジェクトに変換、もしくはその逆を行うマッピングサービス。

– デフォルトでXMLやJSON用(JAXBElement)のプロバイダは用意されているので、通常は自作する必要はない。(JAXB/BadgerFishアダプタ)

28

@Provider@Consumes(MediaType.APPLICATION_XML)public class CustomerReader implements MessageBodyReader<Customer> { @Override public boolean isReadable(...) {…}

@Override public Customer readFrom(..., InputStream inputStream) {…}}

@Provider@Produces(MediaType.TEXT_PLAIN)public class CustomerWriter implements MessageBodyWriter<Customer> { @Override public boolean isWritable(...) {…}

@Override public void writeTo(Customer customer, ..., OutputStream outputStream) {…}}

Page 29: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● エンティティプロバイダ(続き)

29

@Path(“/customers”)public class CustomerResource { @GET public List<Customer> get...() {...}

@GET @Path(“/{customerid}”) public Customer get...( @PathParam(“customerid”) String customerId, @QueryParam(“zip”) String zip) {…}

@POST public Response create...( @QueryParam(“zip”) String zip, Customer customer) {…}

@PUT public Response update...( JAXBElement<Customer>) {...}

}

CustomerをXMLにwriteToするMessageBodyWriter

GETAccept: XML

CustomerをXMLからreadFromするMessageBodyReader

POSTAccept: XML+XML

(デフォルトの)XML出力MessageBodyWriter

XML

XML

Page 30: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● HTTPメソッド– publicメソッドに@GET/@POST/@PUT/@DELETEを付加すると

リソースメソッドとなる。

– リソースメソッドはvoid、ResponseもしくはJava型を返却。Java型の場合はエンティティプロバイダによってXMLやJSONに変換される。

30

@Path(“/customers”)Public class CustomerResource { @GET Public List<Customer> getListOfCustomers() {…}

@POST @Consumes(MediaType.APPLICATION_XML) public Response createCustomer(JAXBElement<Customer> element) {…}

@PUT @Path(“/{customerid}”) @Consumes(MediaType.APPLICATION_XML) public Response updateCustomer(@PathParam(“customerid”) String customerId, JAXBElement<Customer> element) {…}

@DELETE @Path(“/{customerid}”) public void deleteCustomer(@PathParam(“customerid”) String customerId) {…}}

Page 31: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● コンテキスト情報– @Contextにより各種情報(下記)を属性もしくはメソッド引数にイ

ンジェクションできる。

31

コンテキスト情報 属性 引数 説明

HttpHeaders ○ リクエストHTTPヘッダの各種値の取得httpHeaders.getAcceptableLanguages()// Accept-Language値

UriInfo ○ ○ リソースのURI情報uriInfo.getAbsolutePathBuilder()// 自リソースの絶対パスURIビルダー

Request ○ HTTPメソッドの種類、キャッシュ関連情報request.getMethod()// HTTPメソッド

SecurityContext ○ ○ セキュリティ関連情報の取得secureContext.isSecure()// HTTPSか否か

Providers ○ ○ エンティティプロバイダや例外マッピングプロバイダの取得providers.getMessageBodyWriter(...)// マッチするエンティティプロバイダ(Writer)の取得

Page 32: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● Response– メタ情報をクライアントに返却したい場合にbuildして返却する。

● ステータスコード(デフォルトだと200 OK)

– POST/PUTの正常時に201 Createdを返却するよう変更– エラーコード返却するよう変更(後述)

● Location(URI)

– POST/PUTの正常時に作成・修正リソースのURI● レスポンスHTTP本体

32

@POST public Response createNewBook(JAXBElement<Book> bookJaxb) { ... URI bookUri = uriInfo.getAbsolutePathBuilder().path( Book.getId().toString()).build();

// 返却メタ情報:ステータスコード201 Created、かつLocation=生成リソースのURI return Response.created(bookUri).build();}

Page 33: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● 例外処理– エラーステータスコードを充てたResponseを引数にしてWebApplicatio

nExceptionをスロー

– 例外マッピングプロバイダを使用れば、任意の非チェック例外をWebApplicationExceptionにチェインできる。

– いずれにも該当しないの非チェック例外はServletまでスローされつづけ、ServletコンテナがInternalServerError500を返却する。

33

// HTTP本体にメッセージを付けてステータスコード400を返却throw new WebApplicationException( Response.status(400).entity(“Id must be a positive integer!”).build());

// 404 NotFoundthrow new WebApplicationException(Response.Status.NOT_FOUND);

@ProviderPublic class EntityNotFoundMapper implements ExceptionMapper<javax.persistence.EntityNotFoundException> { Public Response toResponse(EntityNotFoundException ex) { return Response.status(404).entity(ex.getMessage()).build());}

Page 34: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● RESTサービスのパスの設定– Jerseyに渡すURLパターンを設定する。

34

// ${コンテキストルート/rs/以下のURIがリクエストされたらRESTとみなし、Jerseyに渡す}@ApplicationPath(“rs”)public class ApplicationConfig extends Application {}

Page 35: Beginning Java EE 6 勉強会(7) #bje_study

JAX-RSモデル

● ライフサイクル(EJB)– JAX-WS(SOAP)と同じ

35

存在しない状態

準備状態

@PostConstruct @PreDestroy

メソッド呼び出し

Page 36: Beginning Java EE 6 勉強会(7) #bje_study

演習

● ソースコードを熟読(ex14.BookResource14)

● ビルド+デプロイ

● cURLでGET/POST/DELETE

● リクエストのAcceptやContent-Typeを変えてみる

● PUT(Bookの修正)に対応させる

※リクエスト文はソースコードにコメントで書かれているのでcopy&pasteしてください

36

Page 37: Beginning Java EE 6 勉強会(7) #bje_study

演習

● 修正– JSONArrayが見つからないエラーが発生する場合は、chapter15配下pom.xmlに以下のリポジトリを追加する。

– NetBeansでdeployした場合のURIは”chapter15/rs/14/books”になります。

– おまけで用意されているManagedBeanは腐っています。

● 動かしたい場合は頑張ってください。

37

<dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> <version>1.3.1</version> </dependency>

Page 38: Beginning Java EE 6 勉強会(7) #bje_study

SOAP or REST?● REST と SOAP ではどちらが優れていますか

● セキュリティについて、SOAP は REST より優れているのではありませんか

● トランザクションについてはどちらが優れていますか

● 相互運用性について、SOAP は相互運用性が考慮されており、REST よりも優れているのではありませんか

● メタデータについてはどうでしょう。REST の相互運用性が高いとしても、REST には WSDL が存在せず、WSDL が存在しなければサービスを呼び出すクライアント側プロキシを生成できないため、使いにくくありませんか

● HTTP 以外のトランスポートを使用するにはどうすればよいでしょう

● ここまでの答えをまとめると、REST はインターネットに接続しているアプリケーションに適し、SOAP はエンタープライズ アプリケーションに適していることになりますか

38

続きはhttp://msdn.microsoft.com/ja-jp/magazine/dd942839.aspx