51
HASUNUMA Kenji GlassFish Users Group Japan

eXtreme JAX-RS

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: eXtreme JAX-RS

HASUNUMA KenjiGlassFish Users Group Japan

Page 2: eXtreme JAX-RS

JAX-RSJersey

Since 2008

Page 3: eXtreme JAX-RS

JAX-RS = HTTPを直接扱う高水準API

Page 4: eXtreme JAX-RS

WARMING UP!HTTP & JAX-RS

Page 5: eXtreme JAX-RS

JAX-RSを極めるための予備知識

HTTPとは?

•リクエスト/レスポンス型の通信方式•状態を持たない(ステートレス)•オクテットのストリームで表現、TCPで送受信

Page 6: eXtreme JAX-RS

JAX-RSを極めるための予備知識

TCPとは?

•オクテットのストリーム送受信方式• IPを利用してネットワーク上に通信経路を確立

•異なるアプリケーションで通信を多重化(ポート)

Page 7: eXtreme JAX-RS

JAX-RSを極めるための予備知識

IPとは?•物理的・論理的データリンクに依存しないパケット通信

• 32ビット(IPv4)/128ビット(IPv6)のアドレスでノードを識別

• IPsecで暗号化…IPv4はオプション、IPv6は標準

Page 8: eXtreme JAX-RS

JAX-RSを極めるための予備知識

JAX-RSとは?

• Java EEでHTTPを直接扱う高水準API

• HTTPのリクエスト/レスポンスと対応

• Servletの実装(自身はWebアプリケーション)

Page 9: eXtreme JAX-RS

JAX-RSを極めるための予備知識

Servletとは?

•リクエスト/レスポンス型の通信を扱うJava EE API

•送受信にSocketを使用、全体をスレッドで処理する

•コンテナーと呼ばれるプロセスが制御

Page 10: eXtreme JAX-RS

JAX-RSを極めるための予備知識

Socketとは?

• TCP/UDPの通信をファイルI/Oと同様のインタフェースで扱う仕組み

•送信 = Write、受信 = Read

• JavaではStream/Channelとして実装

Page 11: eXtreme JAX-RS
Page 12: eXtreme JAX-RS

Request & Response

Page 13: eXtreme JAX-RS

JAX-RSの処理フロー

Page 14: eXtreme JAX-RS

(Request -- HTTP)

GET /greeting/say/hello?name=JJUG HTTP/1.1

Content-Type: application/x-www-form-urlencoded

User-Agent: JAX-RS Client

Host: localhost:8080 Request Header

Request Body

[CR + LF]

Page 15: eXtreme JAX-RS

(Response -- HTTP)

HTTP/1.1 200 OK

X-Powered-By: Servlet/3.0 JSP/2.2

Server: GlassFish Server Open Source Edition 3.1.2.2

Content-Type: text/plain

Transfer-Encoding: chunked

Date: Thu, 09 May 2013 19:02:28 GMT

Hello, JJUG

Response Header

Response Body

[CR + LF]

Page 16: eXtreme JAX-RS

/* Request -- JAX-RS Client API */

public class Hello {

public static void main(String... args) {

Client client = ClientBuilder.newClient();

WebTarget target =

client.target("http://localhost:8080/greeting/say/hello")

.queryParam("name", "JJUG");

String message =

target.request("application/x-www-form-urlencoded")

.header("User-Agent", "JAX-RS Client")

.get(String.class);

System.out.printf("Response: %s\n", message);

}

}

Page 17: eXtreme JAX-RS

/* Response -- JAX-RS Server API */

@Path("/hello")

public class HelloResource {

@GET

@Produces("text/plain")

public String sayHello(@QueryParam("name") String name) {

return String.format("Hello, %s", name);

}

}

Page 18: eXtreme JAX-RS

JAX-RSのリクエスト処理

•すべての要素を読み取ることができる•ほとんどの場合、直接Javaデータ型にマッピング可能

•パラメーターの妥当性を検査できる (Bean Validation、JAX-RS 2.0)

Page 19: eXtreme JAX-RS

リソースクラスのメソッド引数アノテーション 設定される値@QueryParam クエリー・パラメーターの値@FormParam フォーム・パラメーターの値@PathParam URIの一部

@MatrixParam Matrix URIの属性部分@HeaderParam リクエストヘッダーの値@CookieParam クッキーの値

(なし) リクエストボディー

Page 20: eXtreme JAX-RS

JavaクラスとMIMEタイプの対応Javaクラス MIMEタイプ

byte[ ]任意のMIMEタイプ

(*/*)String 任意のMIMEタイプ

(*/*)InputStream任意のMIMEタイプ

(*/*)Reader

任意のMIMEタイプ(*/*)

JavaBean(JAXB)

text/xmlJavaBean

(JAXB) application/xmlJavaBean(JAXB)

application/jsonMultivaluedMap application/x-www-urlencoded

Booleantext/plain

※プリミティブ型はauto-boxingCharacter text/plain※プリミティブ型はauto-boxing

Number

text/plain※プリミティブ型はauto-boxing

Page 21: eXtreme JAX-RS

JAX-RSのレスポンス処理

•あらゆる形式のレスポンスを生成可能•メソッド戻り値にボディーを設定→HTTP 200

•例外スロー →HTTP 4xx/5xx

•パラメーター不正 (Bean Validation)→HTTP 400 (JAX-RS 2.0)

Page 22: eXtreme JAX-RS

Multipart Message

Page 23: eXtreme JAX-RS

マルチパート・リクエスト

Page 24: eXtreme JAX-RS

JAX-RSのマルチパート・リクエスト対応

• JAX-RS 1.0以前から、各実装がマルチパート・リクエスト処理を用意

• POSTメソッドによるファイルのアップロード処理を実現可能

• JAX-RS 2.0当初から標準化対象外

Page 25: eXtreme JAX-RS

マルチパート処理の概要

•マルチパート・リクエストにマッピングするクラスを用意→Iteratorパターンでエンティティーを取得する

• Jersey、RESTEasyには専用のアノテーションを使用する方法もあり

Page 26: eXtreme JAX-RS

@POST@Consumes(“multipart/form-data”)@Path(“/upload”)public void upload(MultiPart multiPart) { final String home = System.getProperty(“user.home”); for (BodyPart bodyPart : multiPart.getBodyParts()) { String name = bodyPart.getContentDisposition().getFileName(); if (name != null) { BodyPartEntity bodyPartEntity = (BodyPartEntity) bodyPart.getEntity(); Files.copy(bodyPartEntity.getInputStream(), Paths.get(home, name), REPLACE_EXISTING); } }}

Jersey

Page 27: eXtreme JAX-RS

@POST@Consumes(“multipart/form-data”)@Path(“/upload”)public void upload(MultiPartFormDataInput input) { final String home = System.getProperty(“user.home”); List<InputPart> parts = input.getFormDataMap().get(“file”); for (InputPart part : parts) { String name = getName(part.getHeaders()); InputStream in = part.getBody(InputStream.class, null); Files.copy(in, Paths.get(home, name), REPLACE_EXISTING); }}

RESTEasy

Page 28: eXtreme JAX-RS

@POST@Consumes(“multipart/form-data”)@Path(“/upload”)public void upload(InMultiPart inMultiPart) { final String home = System.getProperty(“user.home”); while (inMultiPart.hasNext()) { InPart part = inMultiPart.next(); MultivaluedMap<String, String> headers = part.getHeaders(); String name = headers.getFirst(“Content-Disposition”); InputStream in = part.getInputStream(); Files.copy(in, Paths.get(home, name), REPLACE_EXISTING); }}

Apache Wink

Page 29: eXtreme JAX-RS

完全なサンプルhttps://github.com/btnrouge

• btnrouge/jerseysamples

• btnrouge/resteasysamples

• btnrouge/winksamples

• btnrouge/JerseyUploader

• btnrouge/RESTEasyUploader

Page 30: eXtreme JAX-RS

DeployingJAX-RS

Page 31: eXtreme JAX-RS

JAX-RSのデプロイ方法

JAX-RS実装を含むJava EEサーバー

• Applicationのサブクラス+ @ApplicationPath で設定 ←おすすめ

その他(サーブレットコンテナー等)

• web.xmlに実装Servlet、Applicationのサブクラス名を登録 ←結構面倒

Page 32: eXtreme JAX-RS

Applicationクラスについて

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

•リソースクラスのSetを返すようにオーバーライドする

• @ApplicationPath付加時はオーバーライド不要

Page 33: eXtreme JAX-RS

TomcatやJetty等でJAX-RSを使うには?

•リソースクラスを洗い出す• Applicationのサブクラスを作成する

•実装Servletをweb.xmlに登録する

• <init-param>にApplicationのサブクラス名を設定する

Page 34: eXtreme JAX-RS

<servlet> <servlet-name>ServletContainer</servlet-name> <servlet-class>com.sun.jersey.spi.container. ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>jp.coppermine.extremejaxrs.jersey. MyApplication</param> </init-param></servlet><servlet-mapping> <servlet-name>ServletContainer</servlet-name> <url-pattern>/rest/*</url-pattern></servlet-mapping><!-- Apache Wink : org.apache.wink.server.internal.servlet.RestServlet -->

Jersey

Page 35: eXtreme JAX-RS

<servlet> <servlet-name>HttpServletDispatcher</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet. HttpServletDispatcher</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>jp.coppermine.extremejaxrs.resteasy. MyApplication</param> </init-param></servlet><servlet-mapping> ... </servlet-mapping><context-param> <param-name>resteasy.servlet.mapping.prefix </param-name> <param-value>/rest</param-value></context-param>

RESTEasy

Page 36: eXtreme JAX-RS

完全なサンプルhttps://github.com/btnrouge

• btnrouge/jerseysamples

• btnrouge/resteasysamples

• btnrouge/winksamples

Page 37: eXtreme JAX-RS

JAX-RS Auth.

Page 38: eXtreme JAX-RS

JAX-RSのセキュリティー

•認証はServletコンテナーに依存

•認可は以下2種類の組み合わせ• Servletセキュリティー(標準)

• Common Annotations(ロールベース)

※Common Annotationsを使うには工夫が必要

Page 39: eXtreme JAX-RS

Servletセキュリティーとは?

• Servletコンテナーで認証

•アプリケーションで認可• <security-constraint> : 対象(メソッドまたはURI)と認可 (ロールベース)

• <security-role> : ロール定義

Page 40: eXtreme JAX-RS

Servletセキュリティー(補足)

<security-constraint>は下記アノテーションで代替可能

• @ServletSecurity

• @HttpConstraint

• @HttpMethodConstraint

Page 41: eXtreme JAX-RS

Common Annotationsを用いた認可

アノテーションによる認可

• @RolesAllowed : 指定ロールを許可

• @PermitAll : 全ロール許可

• @DenyAll : 全ロール拒否

@DeclareRoles : <security-role>の代替

Page 42: eXtreme JAX-RS

JAX-RS認証/認可サンプル

• JAX-RSでアノテーションベースの認証/認可を実現する

• web.xmlを作成せず、すべてアノテーションだけで実装する。

•実装 : Jersey、コンテナ : GlassFish

Page 43: eXtreme JAX-RS

@DeclareRoles({“member”, “leader”})@Path(“/docs”)public class AuthResource { @RolesAllowed(“member”) @GET @Path(“/information”) public String getInformation() { /* snip */ }

@RolesAllowed(“leader”) @GET @Path(“/confidential”) public Stirng getConfidential() { /* snip */ }}

Page 44: eXtreme JAX-RS

@ServletSecurity( @HttpConstraint(rolesAllowed = “member”) )@WebServlet(urlPatterns = “/rest/*”, initParams = @WebInitParam( name = “com.sun.jersey.spi.container. ResourceFilters”, value = “com.sun.jersey.api.container.filer. RolesAllowedResourceFilterFactory”) )public class MyServletContainer extends ServletContainer { // not implemented}

Page 45: eXtreme JAX-RS

完全なサンプルhttps://github.com/btnrouge

• btnrouge/jerseyauthsamples

Page 46: eXtreme JAX-RS

JAX-RS for Web Applications

Page 47: eXtreme JAX-RS

JAX-RSとWebアプリケーション

• JAX-RSはHTTPを扱うAPI→Webアプリケーションも適用対象

• Servlet Context等の注入→HTTPセッションも利用可能

• JAX-RS 1.0リリース前から様々な試み(例) Jersey MVC Framework

Page 48: eXtreme JAX-RS

コンテキストの注入@Context で以下コンテキストを注入可能

• ServletConfig

• ServletContext

• HttpServletRequest

• HttpServletResponse→サーブレットの機能を直接利用可能(例) HttpSession、リダイレクト

Page 49: eXtreme JAX-RS

Jersey MVC Framework

• Jersey黎明期(JAX-RS 0.x)から存在

• JSP、Velocity、FreeMakerに対応

•テンプレート名 + パラメーター→指定のエンジンでレンダリング

•他のテンプレートエンジンに対応するための拡張ポイントもあり

Page 50: eXtreme JAX-RS

JAX-RS is “Golden Hammer”

• HTTPのほぼすべてを扱える

• Java EEの認証/認可メカニズムが有効

•ステートフルな実装も可能•Webサービス、Webアプリケーションの両方に適用できる

Page 51: eXtreme JAX-RS

HASUNUMA KenjiGlassFish Users Group Japan

[email protected]: @btnrouge