java eeハンズオン資料 jjug ccc 2015 fall

113
(C) CASAREAL, Inc. All rights reserved. Struts&独自フレームワーク! 今からでも遅くない Java EE Web開発入門ハンズオン! 株式会社カサレアル 多田真敏 (@suke_masa) JJUG CCC 2015 Fall 2015/11/28() 1

Upload: masatoshi-tada

Post on 07-Jan-2017

9.598 views

Category:

Technology


5 download

TRANSCRIPT

(C) CASAREAL, Inc. All rights reserved.

脱Struts&独自フレームワーク!

今からでも遅くない

Java EE Web開発入門ハンズオン!株式会社カサレアル

多田真敏 (@suke_masa)

JJUG CCC 2015 Fall

2015/11/28(土)1

(C) CASAREAL, Inc. All rights reserved.

このセッションについて

uハッシュタグ

#ccc_m1

u Java EEのWebアプリケーション開発について、演習を交えながら学習します

2

(C) CASAREAL, Inc. All rights reserved.

自己紹介

u多田真敏(ただまさとし)

u大阪出身、香川育ちの0x1F歳

u (株)カサレアル所属

u Java EEを中心とした研修トレーナー

u JJUG CCCは4回連続4回目の出場

u Twitter:@suke_masa

3

4年前の写真なので実物はもうちょっとおっさん…

(C) CASAREAL, Inc. All rights reserved.

本資料について

u著作権は(株)カサレアルに帰属します。

u個人の学習、コミュニティや社内の勉強会など、 「無償の用途」にのみご利用ください。

u 勉強会の場合、会場代など「運営に最低限必要な費用」を参加者の方から集金する事については「無償の用途」の範囲内とします。

u本資料を使用して有償のサービスを提供することを禁止します。また、有償サービスで利用する資料への内容の転載も禁止します。

4

(C) CASAREAL, Inc. All rights reserved.

本日のスケジュール

5

u 13:00-13:10 Java EE全体像の講義

u 13:10-13:50 JSF講義・演習

u 13:50-14:00 10分休憩

u 14:00-14:40 JAX-RS講義・演習

u 14:40-14:50 Jersey MVC + MVC 1.0講義

(C) CASAREAL, Inc. All rights reserved.

①Java EEの全体像

6

(C) CASAREAL, Inc. All rights reserved.

背景:Struts 1とSeasar2の終焉

u2013年 Struts 1.x EOL

u 開発ストップは2008年から

(7年前に終わっていた)

u2016年9月26日 Seasar2 EOL予定

u 2015年9月のSeasar Conferenceで発表 http://d.hatena.ne.jp/higayasuo/20150928/1443415547

7

(C) CASAREAL, Inc. All rights reserved.

背景:脱・独自フレームワーク

u作った社員が異動・退職したら保守できない

u一般に公表されないものなので、開発者の教育や外部調達が難しい

u長く使っていて古くなってきた

8

なるべく、世の中で広く使われている 「一般的な」フレームワークが求められている

(C) CASAREAL, Inc. All rights reserved.

現在のトレンド

Java EE or Spring Framework

u Java EE u 標準仕様=長期的な安定性

u APサーバーも含めたベンダーサポート

u Spring Framework u 進化の速さがすごい=Javaの最先端

u 高機能・高生産性

9

(C) CASAREAL, Inc. All rights reserved.

なぜJava EEなのか?

u「標準」は「一般的」の最上級

u最先端ではないが十分に現代的なフレームワーク u 最先端が「最善の選択」かは時と場合による

u仕様面・サーバー面での長期的安定性

10

(C) CASAREAL, Inc. All rights reserved.

Java EE=フルスタックフレームワーク

11

JSF

JAX-RS

WebSocket

CDI/EJB /JTA JPA

Interceptor

Bean Validation

Servlet/JSP

Web ビジネスロジック DBアクセス

(C) CASAREAL, Inc. All rights reserved.

Java EE 7対応APサーバー

(2015年11月時点)

uGlassFish/Payara uWildFly uWebLogic ← 今年10月リリース!

uWebSphere uCosminexus

u JBossは来年かも?12

(C) CASAREAL, Inc. All rights reserved.

Java EEは「仕様」

u Javadocを見ると、ほとんどインタフェース・アノテーション・例外

uAPサーバーは「実装」の集合体

u細かな挙動は「実装」によって異なる部分もあるので注意

13

(C) CASAREAL, Inc. All rights reserved.

今回の環境

uPayara Web ML 4.1.1.154 u GlassFish 4.1.1をベースに、英国C2B2社がバグ修正・機能強化を行っているサーバー

u GlassFishはJava EEの参照実装 (Reference

Implementation : RI)

uJDK 8u66 uNetBeans 8.1 (8.0.2でもOK)

uJavaDB (Payara内包)

14

(C) CASAREAL, Inc. All rights reserved.

事前準備の確認

uNetBeans・Payara・curlはインストール済み?

uプロジェクトはクローン・ビルド済み?

uexerciseブランチに切り替え済み?

uアクション項目は表示済み?

15

(C) CASAREAL, Inc. All rights reserved.

今回の課題

u架空の社員管理システム u 社員データの検索・追加・更新・削除を行う

u同じシステムをJSF/JAX-RS/Jersey MVCという違う技術で実装します

uこれからデモします

16

(C) CASAREAL, Inc. All rights reserved.

②JSF講義・演習

17

(C) CASAREAL, Inc. All rights reserved.

JSF (JavaServer Faces)とは?

uHTMLを返すWebフレームワーク

uコンポーネントベース

u .NET、Android、Swing、JavaFXなどのGUIアプリ経験がある人は馴染みやすい

u Strutsなどのアクションベースフレムーワークから移行する人は、最初は違和感があるかも

18

(C) CASAREAL, Inc. All rights reserved.

JSF実装

uMojarra (RI) u GlassFish/Payara/WebLogic/WildFly/JBoss内包

u 読み方は「モハラ」

uApache MyFaces u WebSphere内包

19

(C) CASAREAL, Inc. All rights reserved.

JSFアプリの最小構成

uBacking Bean(Javaクラス)

uFacelets(画面)

uweb.xml(設定ファイル)

20

(C) CASAREAL, Inc. All rights reserved.

Backing Bean

u画面に対応したJavaクラス u 「Managed Bean(管理Bean)」と呼ばれることもありますが、 これは他の仕様でも使われる用語なので、区別する為に本セッションでは「Backing Bean」と呼びます

21

@Named @ViewScoped public class EmpBean { private String name; // setter/getterも必要

public String findByName() { return "index.xhtml"; } }

(C) CASAREAL, Inc. All rights reserved.

Facelets

uXHTML形式のビュー技術

u JSPのようなJavaコードは書けない→ビューとロジックの完全な分離が可能

22

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html"> <h:head><title>社員一覧</title></h:head>

<h:body> <h:form> 氏名キーワード:<h:inputText value="#{empBean.name}" />

<h:commandButton action="#{empBean.findByName()}" value="検索">

(C) CASAREAL, Inc. All rights reserved.

web.xml

uFacesServletの登録が必要

23

<web-app> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <web-app>

(C) CASAREAL, Inc. All rights reserved.

Backing Beanの作り方①

名前付けアノテーションをクラスに付加uEL式でビューから呼び出す際の名前を付ける u デフォルトはクラス名の頭文字を小文字にしたもの

24

// 下記の3つは全て同じ意味

@Named public class EmpBean { … }

@Named("empBean") public class EmpBean { … }

@Named(value = "empBean") public class EmpBean { … }

(C) CASAREAL, Inc. All rights reserved.

Backing Beanの作り方②

スコープアノテーションをクラスに付加u@ViewScoped

u 1つの画面が有効な限りBacking Beanインスタンスも有効

u 最もよく利用する

u@ConversationScoped, @FlowScoped u 開始・終了を明示的に指定して、その間はずっとBacking Beanインスタンスも生きている

u 複数画面で値を受け渡すときに便利

u@RequestScoped, @SessionScoped, @ApplicationScoped, @Dependentはあまり使わない

25

@Named @ViewScoped public class EmpBean { … }

(C) CASAREAL, Inc. All rights reserved.

★演習★ Backing Beanの作成

u演習1-1:Backing Beanクラスに@Named

と@ViewScopedを付加する

26

(C) CASAREAL, Inc. All rights reserved.

Backing Beanの作り方③

画面と値を受け渡すフィールドu画面からはEL式で紐付けられる

u setter/getter必須

27

@Named @ViewScoped public class EmpBean { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }

(C) CASAREAL, Inc. All rights reserved.

Backing Beanの作り方④

アクションメソッドuボタンが押された際の処理を記述する

u画面からはEL式で紐付けられる

uStringでフォワード先のビュー名を返す

uvoidまたはnullの場合、現在と同じ画面に遷移する

28

@Named @ViewScoped public class EmpBean { @Inject BizLogic logic;

public String find() { logic.doSomething(); return "index.xhtml"; } }

(C) CASAREAL, Inc. All rights reserved.

★演習★ Backing Beanの作成

u演習1-2:アクションメソッドの中身を実装する

u検索のキーワードを受け取るnameフィールド、そのsetter/getterは作成済み

29

(C) CASAREAL, Inc. All rights reserved.

画面の作り方①

JSFタグによる記述unamespaceを指定

u hタグ→HTMLタグの生成

u fタグ→Ajaxや入力値の変換・検証など

30

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html"> <h:head><title>社員一覧</title></h:head>

<h:body> <h:form> 氏名キーワード:<h:inputText value="#{empBean.name}" />

<h:commandButton action="#{empBean.findByName()}" value="検索">

(C) CASAREAL, Inc. All rights reserved.

画面の作り方②

EL式によるBacking Beanとの紐付けu#{Bean名.プロパティ名}で指定

u Bean名は@Namedで付けたもの

31

氏名キーワード:

<h:inputText value="#{empBean.name}" /> <h:commandButton action="#{empBean.findByName()}" value="検索">

@Named @ViewScoped public class EmpBean { private String name; public String findByName() { // do something return "index.xhtml"; } }

(C) CASAREAL, Inc. All rights reserved.

★演習★ 社員一覧画面の作成

u演習1-3:ボタンが押された際のアクションメソッドをEL式で指定する

u演習1-4:tableに社員リストを一覧表示する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]

uWindows PCの方は、セキュリティ警告が出たら[許可]してください

32

※データベースが

DROP-CREATE-INSERT されます

(C) CASAREAL, Inc. All rights reserved.

【補足】Converterによる型変換

uビューの入出力値(String)と、Javaの型を相互変換する

33

<html xmlns="…" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core"> <h:inputText value="#{emp.joinedDate}"> <f:convertDateTime pattern="yyyy-MM-dd" timeZone="Asia/Tokyo"/> </h:inputText>

@Named @ViewScoped public class EmpBean { private java.util.Date joinedDate; … }

(C) CASAREAL, Inc. All rights reserved.

【参考】HTML5 Friendly Markup

uJSF 2.2 (Java EE 7)からの新機能

u通常のHTML5タグのように記述できる

uとは言え、JSFタグの属性などの知識も必要

34

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsf="http://xmlns.jcp.org/jsf"> 氏名キーワード:

<input type="text" jsf:value="#{empBean.name}" />

(C) CASAREAL, Inc. All rights reserved.

Bean Validation

uBacking Beanのフィールドに@NotNullなどのアノテーションを付ける

35

@Named @ViewScoped public class EmpBean { @NotNull @Size(min = 1, max = 10) @Pattern(regexp = "[a-zA-Z]*") private String name; … }

(C) CASAREAL, Inc. All rights reserved.

検証アノテーション(一部)u@NotNull

u nullの場合に検証エラー

u@Pattern u 指定した正規表現と一致しなければエラー

u regexp属性に正規表現を指定

u@Size u 指定した文字列長の最大値・最小値の範囲内でなければエラー

u min属性に最小値を指定(デフォルト値:0)

u max属性に最大値を指定(デフォルト値:Integer.MAX_VALUE)

36

(C) CASAREAL, Inc. All rights reserved.

エラーメッセージの指定

uクラスパスルートのValidationMessages.propertiesに記述する

uメッセージのキーはアノテーションのmessage

属性に{}付きで指定する

37

@Named @ViewScoped public class EmpBean { @NotNull(message = "{message.notnull}") private String name; …

(C) CASAREAL, Inc. All rights reserved.

★演習★ バリデーション

u演習2-1:Backing Beanのnameプロパティに検証アノテーションを追加

38

(C) CASAREAL, Inc. All rights reserved.

画面にエラーメッセージを表示

uh:messagesタグで表示する

39

<h:messages id="error" errorStyle="color:red" />

Facelets

ブラウザ

(C) CASAREAL, Inc. All rights reserved.

★演習★ バリデーション

u演習2-2:画面にエラーメッセージ表示のタグを追加する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]40

※データベースが

DROP-CREATE-INSERT されます

(C) CASAREAL, Inc. All rights reserved.

【補足】発展的なバリデーション

uhttp://yamkazu.hatenablog.com/entry/20110206/1296985545 を読むと、Bean

Validationを一通り学べます

u 複数のアノテーションをまとめて1つのアノテーションにできる

u 独自の検証ロジックを持ったアノテーションを自作できる

u 複数のアノテーションをグループ化できる41

(C) CASAREAL, Inc. All rights reserved.

【補足】相関バリデーション (複数の入力項目にまたがった検証)u一工夫が必要。やり方は様々

u http://yoshio3.com/2015/03/26/jsf-multiple-validation/

u http://d.hatena.ne.jp/Yosuke_Taka/20120131/1327983465

u http://den2sn.hatenablog.com/entry/2014/12/22/092738

u http://n-agetsuma.hatenablog.com/entry/2012/11/18/231527

u JSF 2.3(Java EE 8)で標準仕様に入る予定

42

(C) CASAREAL, Inc. All rights reserved.

Ajaxの利用

u JavaScriptコード無しでAjaxを利用できる

u f:ajaxタグ

u execute属性:リクエスト時に送信する値を指定

u render属性:レスポンスで返ってきた情報を描画する部分を指定

43

(C) CASAREAL, Inc. All rights reserved.

Ajaxの利用

u通常

uAjax

44

<h:commandButton action="#{empBean.findByName()}" value="検索" />

<h:commandButton action="#{empBean.findByName()}" value="検索">

<f:ajax execute="@form" render=":employeeList :error"/> </h:commandButton>

(C) CASAREAL, Inc. All rights reserved.

★演習★ 検索のAjax化

u演習3:<f:ajax>タグで、ボタンが押された際の挙動をAjaxに変更する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]45

※データベースが

DROP-CREATE-INSERT されます

(C) CASAREAL, Inc. All rights reserved.

GET時のクエリパラメータの受け取り

u JSFは基本的にすべてPOSTで遷移する

uGETでのクエリパラメータ取得はFaceletsに 下記の記述が必要

46

<h:body> <f:metadata> <f:viewParam id="empId" name="empId" value="#{employeeEditBean.empId}"/> </f:metadata> …

クエリ パラメータ名

Backing Bean プロパティ名

(C) CASAREAL, Inc. All rights reserved.

★演習★ クエリパラメータの

    受け取りu演習4-1:Faceletsにf:viewParamタグを記述する

47

(C) CASAREAL, Inc. All rights reserved.

@ConversationScoped (会話スコープ)

u会話の開始から終了まで、そのBacking

Beanは生存している

u登録→確認→完了のような、複数画面で値を受け渡す際に有用

u 画面にhiddenタグを埋め込んで値をやりとりするなどの必要なし

48

(C) CASAREAL, Inc. All rights reserved.

@ConversationScoped (会話スコープ)

49

@Named @ConversationScoped public class EmpBean { @Inject Conversation conversation; public String one() { conversation.setTimeout(60000); conversation.begin(); return "one.xhtml"; } public String two() { return "two.xhtml"; } public String three() { conversation.end(); return "three.xhtml"; } }

uConversationを@InjectでDI

ubegin()で会話開始

uend()で会話終了

(C) CASAREAL, Inc. All rights reserved.

★演習★ 会話スコープの利用

u演習4-2:Backing Beanを会話スコープにする

u演習4-3:会話を開始する

u演習4-4:会話を終了する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]

50

※データベースが

DROP-CREATE-INSERT されます

(C) CASAREAL, Inc. All rights reserved.

日本語書籍について

uBegining Java EE 6 u Managed Beanの作り方が違う (@ManagedBeanを付加する)

u スコープアノテーションが別パッケージの古いもの

u 例:

u EE 6 → javax.faces.bean.ViewScoped u EE 7 → javax.faces.view.ViewScoped

uマスタリングJava EE 5

u ビューがJSP

u 内部の仕組みなどはほぼ変わらない51

(C) CASAREAL, Inc. All rights reserved.

その他に知っておいたほうが良いこと

uまずは菊田さんのJava Day Tokyo 2015の資料を確認しましょう https://www.youtube.com/watch?v=yW_LAa9FXAo

uアプリケーションライフサイクル

u例外処理

uリッチコンポーネントPrimeFaces

uユーティリティライブラリOmniFaces

52

(C) CASAREAL, Inc. All rights reserved.

③JAX-RS

講義・演習

53

(C) CASAREAL, Inc. All rights reserved.

JAX-RSとは?

u JSONやXMLをレスポンスするREST Webサービス開発のフレームワーク

uシンプルで分かりやすいAPIが特徴

54

(C) CASAREAL, Inc. All rights reserved.

REST Webサービス超概要

u入力 = URL + HTTPリクエストメソッド

u出力 = JSON + HTTPステータスコード

55

GET http://localhost:8080/jjug-jax-rs/api/employees/1

{ "id" : 1, "name" : "Yumi Wakatsuki", … }

(C) CASAREAL, Inc. All rights reserved.

なぜREST Webサービスなのか?

uクライアントの多様化

u PCブラウザ、スマホ・タブレット(ネイティブアプリ・ブラウザ)、別システムとの連携…

uサーバー側はJSONだけ返して、画面表示はクライアントに任せる

uブラウザの場合は、AngularJSなどのJavaScriptフレームワークを併用することが一般的

56

(C) CASAREAL, Inc. All rights reserved.

JAX-RS実装

u Jersey u GlassFish/Payara/WebLogic内包

u RESTEasy u WildFly/JBoss内包

uApache CXF u WebSphere内包(JAX-WS兼用)

57

(C) CASAREAL, Inc. All rights reserved.

JAX-RSアプリの最小構成

uApplicationサブクラス(Javaクラス)

uリソースクラス(Javaクラス)

u設定ファイルは必要なし

58

(C) CASAREAL, Inc. All rights reserved.

Applicationサブクラスの作成

u javax.ws.rs.core.Applicationのサブクラスを作成する

u@ApplicationPathアノテーションにパスを指定する

u下記のコードの場合、「http://localhost:8080/コンテキストルート/api/…」

59

@ApplicationPath("api") public class MyApplication extends Application { // 中身は空でOK

}

(C) CASAREAL, Inc. All rights reserved.

★演習★ Applicationサブクラス

    の作成u演習1-1:Applicationサブクラスの作成

uクラス内にgetProperties()というメソッドがありますが、意味は後ほど説明します

60

(C) CASAREAL, Inc. All rights reserved.

リソースクラス

u@Path+@GETでURLマッピングを指定

u@PathParamでパス内のパラメータを取得

61

(C) CASAREAL, Inc. All rights reserved.

リソースクラスのコード例

62

@Path("employees") public class EmployeeResource { @GET @Path("{id}") public Response find(@PathParam("id") Integer id) { … } }

GET http://<中略>/api / employees / 1

(C) CASAREAL, Inc. All rights reserved.

生成するメディアタイプ

u@Producesアノテーションで、レスポンスのContent-Typeを指定する

63

@Path("employees") public class EmployeeResource { @GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON) public Response find(@PathParam("id") Integer id) { …

(C) CASAREAL, Inc. All rights reserved.

★演習★ リソースクラスの作成

u演習1-2:クラスに@Pathを付加する

u演習1-3:メソッドに@GET、@Path、@Producesを付加する

u演習1-4:メソッドの引数に@PathParamを付加する

64

(C) CASAREAL, Inc. All rights reserved.

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

uHTTPステータスコードと、JSONに変換したいオブジェクトを戻り値にする

65

@GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON) public Response find(@PathParam("id") Integer id) { … return Response. ok(employeeDto) .build(); }

200 OK、employeeDtoをJSON化

(C) CASAREAL, Inc. All rights reserved.

★演習★ リソースクラスの作成

u演習1-5:メソッドの戻り値を記述する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]

u (3) コメント内のcurlコマンドをコマンドプロンプトで実行

66

※データベースが

 DROP-CREATE-INSERTされます

(C) CASAREAL, Inc. All rights reserved.

【補足】MessageBodyWriter

uリソースメソッドの戻り値に渡されたオブジェクトを、JSONやXMLに変換する役割を持つインターフェイス

uオブジェクトの型・@Producesで指定された形式・Acceptリクエストヘッダで、どのMessageBodyWriter実装クラスが動くかが自動的に判断される

67

(C) CASAREAL, Inc. All rights reserved.

【補足】JSONパーサー

uMessageBodyWriter内で使われる、オブジェクトをJSONに変換するライブラリ

uPayara/GlassFishには「MOXy(デフォルト)」「Jackson」「Jettison」が内包

u今回はMOXyを無効化してJacksonを有効化しています

68

(C) CASAREAL, Inc. All rights reserved.

【補足】MOXyの無効化

uApplicationサブクラス内でgetProperties()をオーバーライドし、下記の記述を追加

69

@ApplicationPath("api") public class MyApplication extends Application { @Override public Map<String, Object> getProperties() { Map<String, Object> properties = new HashMap<>(); properties.put(CommonProperties.MOXY_JSON_FEATURE_DISABLE, Boolean.TRUE); return properties; } }

(C) CASAREAL, Inc. All rights reserved.

【補足】Jacksonの有効化

u下記のクラスを作成して@Providerを付加する

70

@Provider public class ObjectMapperResolver implements ContextResolver<ObjectMapper> { @Override public ObjectMapper getContext(Class<?> type) { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enable(SerializationFeature.INDENT_OUTPUT); return objectMapper; } }

(C) CASAREAL, Inc. All rights reserved.

【補足】JAX-RSの例外

uHTTPステータスコードを表す例外が用意されている(下記は一部)

uWebApplicationException uClientErrorException (4xx)

uBadRequestException (400) uNotFoundException (404)

uServerErrorException (5xx) u InternalServerErrorException (500)

71

(C) CASAREAL, Inc. All rights reserved.

【補足】例外処理

uExceptionMapperインターフェイスを実装したクラスに、@Providerアノテーションを付加する

72

@Provider public class WebApplicationExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<WebApplicationException> { @Override public Response toResponse(WebApplicationException exception) { exception.printStackTrace(); // 本来はログを取る

ExceptionDto exceptionDto = createExceptionDto(exception); return Response.status(exception.getResponse().getStatusInfo()) .entity(exceptionDto).build(); } }

(C) CASAREAL, Inc. All rights reserved.

クエリパラメータの取得

u@QueryParamで取得

u@DefaultValueで、そのクエリパラメータが無かった場合のデフォルト値を指定可能

73

@GET @Produces(MediaType.APPLICATION_JSON) public Response findByName( @QueryParam("name") @DefaultValue("") String name) { … }

(C) CASAREAL, Inc. All rights reserved.

Bean Validation

uリソースメソッドの引数に検証アノテーションを指定

74

@GET @Produces(MediaType.APPLICATION_JSON) public Response findByName( @QueryParam("name") @DefaultValue("") @Pattern(regexp = "[a-zA-Z]*") @Size(max = 10) String name) { … }

(C) CASAREAL, Inc. All rights reserved.

★演習★ クエリパラメータ

    による検索u演習2-1:クエリパラメータを取得する

u演習2-2:検証アノテーションの追加

u演習2-3:リソースメソッドの戻り値を記述する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]

u (3) コメント内のcurlコマンドをコマンドプロンプトで実行75

※データベースが

 DROP-CREATE-INSERT  されます

(C) CASAREAL, Inc. All rights reserved.

【補足】検証エラー時は例外が発生

uConstraintViolationExceptionが発生する

uこの例外に対応したExceptionMapperを作っておく必要がある

76

@Provider public class ConstraintViolationExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<ConstraintViolationException> { @Override public Response toResponse(ConstraintViolationException exception) { … } }

(C) CASAREAL, Inc. All rights reserved.

【補足】本セッションにおける 異常時のステータスコードu ID検索→該当IDなしは404、    IDに数字以外が来ても404

u複数件検索→検索結果0件の場合、      200で空のJSON配列を返す

uバリデーションエラー→400

77

(C) CASAREAL, Inc. All rights reserved.

CRUD操作とHTTPリクエストメソッドとHTTPレスポンスステータスコード

78

HTTPリクエスト

メソッドHTTPレスポンス

ステータスコード検索 GET 200 OK追加 POST 201 CREATED更新 PUT 200 OK削除 DELETE 204 NO CONTENT

(C) CASAREAL, Inc. All rights reserved.

POSTによる追加

uメソッドには@POSTを付加

u@ConsumesでリクエストのContent-Typeを指定

79

@POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response insert( EmployeeForm form) { …

(C) CASAREAL, Inc. All rights reserved.

リクエストで送られたJSONの取得

80

@POST @Consumes(…) @Produces(…) public Response insert( EmployeeForm form) { …

{ "name" : "Mai Shiraishi", "joined_date" : "2015-11-28", "department" : { "dept_id" : 1 } }

public class EmployeeForm { private String name; @JsonProperty("joined_date") private String joinedDate; @JsonProperty("department") private DepartmentForm departmentForm = new DepartmentForm(); }

public class DepartmentForm { @JsonProperty("dept_id") private String deptId; }

uリソースメソッドの引数の型のプロパティ名と、JSONのプロパティ名が同じであればOK

(C) CASAREAL, Inc. All rights reserved.

★演習★ POSTによる追加

u演習3-1:リクエストのContent-TypeをMediaType.APPLICATION_JSONに指定する

u@POSTは付加済み

81

(C) CASAREAL, Inc. All rights reserved.

Bean Validation

u前ページのFormクラスの各フィールドに検証アノテーションを付加する

uリソースメソッドの引数に@Validアノテーションを付加

82

public class EmployeeForm { @NotNull @Size(min = 1, max = 40) @Pattern(regexp = "[a-zA-Z\\s]*") private String name;

@DatePattern(pattern = "yyyy-MM-dd") @JsonProperty("joined_date") private String joinedDate;

@Valid @JsonProperty("department") private DepartmentForm departmentForm = new DepartmentForm();

@POST @Consumes(…) @Produces(…) public Response insert( @Valid EmployeeForm form) { …

(C) CASAREAL, Inc. All rights reserved.

レスポンス

u201 CREATEDを返す

u追加が完了したデータを表すURLをlocationレスポンスヘッダに追加する

83

@POST @Consumes(…) @Produces(…) public Response insert(@Valid EmployeeForm form) { … URI location = uriInfo.getAbsolutePathBuilder() .path(employee.getEmpId().toString()).build(); return Response.created(location) .entity(employeeDto).build(); }

(C) CASAREAL, Inc. All rights reserved.

★演習★ POSTによる追加

u演習3-2:リソースメソッドに引数に@Validを付加する

u演習3-3:リソースメソッドの戻り値を記述する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]

u (3) コメント内のcurlコマンドをコマンドプロンプトで実行

84

※データベースが

 DROP-CREATE-INSERT  されます

(C) CASAREAL, Inc. All rights reserved.

【補足】MessageBodyReader

uリクエストから受け取ったJSONやXMLを、リソースメソッドの引数の型に変換する役割を持つインターフェイス

u引数の型と@Consumesで指定された形式で、どのMessageBodyReader実装クラスが動くかが自動的に判断される

85

(C) CASAREAL, Inc. All rights reserved.

【補足】Formクラス・DTOクラス・Entityクラスは分けるu持つべきフィールド・従うべき規約・付加すべきアノテーションが異なるので、似たクラスだが分けたほうが良い

u Form → Bean Validation u DTO → JSON, JAXB u Entity → JPA

86

(C) CASAREAL, Inc. All rights reserved.

PUTによる更新

uメソッドには@PUTと@Consumesを付加

u更新対象の主キーは@Pathで指定

u200 OKとlocationヘッダを返す

87

@PUT @Path("{id}") @Consumes(…) @Produces(…) public Response update(@PathParam("id") Integer id, EmployeeForm form) { … URI location = uriInfo.getAbsolutePath(); return Response.ok(employeeDto) .location(location).build(); }

(C) CASAREAL, Inc. All rights reserved.

★演習★ 更新

u演習4:更新リソースメソッドの戻り値を記述する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]

u (3) コメント内のcurlコマンドをコマンドプロンプトで実行

88

※データベースが

 DROP-CREATE-INSERTされます

(C) CASAREAL, Inc. All rights reserved.

DELETEによる削除

uメソッドには@DELETEを付加

u更新対象の主キーは@Pathで指定

u204 NO CONTENTとlocationヘッダを返す

89

@DELETE @Path("{id}") public Response delete(@PathParam("id") Integer id) { … URI location = uriInfo.getAbsolutePath(); return Response.noContent() .location(location).build(); }

(C) CASAREAL, Inc. All rights reserved.

★演習★ 削除

u演習5:削除リソースメソッドの戻り値を記述する

uここまで出来たら実行してみましょう

u (1)プロジェクトを右クリック→[消去してビルド]

u (2)プロジェクトを右クリック→[実行]

u (3) コメント内のcurlコマンドをコマンドプロンプトで実行

90

※データベースが

 DROP-CREATE-INSERTされます

(C) CASAREAL, Inc. All rights reserved.

日本語書籍について

u JavaによるRESTfulシステム構築

u 日本語書籍はJAX-RS 1.0 (Java EE 6)対応版のみ

u JAX-RS 2.0 (Java EE 7)対応版は、出版されているが英語版のみ

u 日本語版で基礎を身につけた後、EE 7対応の英語版を読むとよい

91

(C) CASAREAL, Inc. All rights reserved.

日本語書籍について

uWeb API : The Good Parts u JAX-RSの本ではないが、RESTの基礎として知っておいたほうが良いことが満載

u URLをどのように設計するか、異常時にどのようなレスポンスを返すかなど

92

(C) CASAREAL, Inc. All rights reserved.

その他に知っておいたほうが良いこと

u本日のうらがみさんの資料を確認しましょう

u特にセキュリティ周りは実装独自機能を多用するので、使用する実装のドキュメントも確認しておきましょう u Jersey:https://jersey.java.net/documentation/latest/

user-guide.html u RESTEasy:http://resteasy.jboss.org/docs.html

u Apache CXF:http://cxf.apache.org/docs/index.html

93

(C) CASAREAL, Inc. All rights reserved.

④Jersey MVC + MVC 1.0

講義

94

(C) CASAREAL, Inc. All rights reserved.

JSF・JAX-RSはStrutsから移行しづらい?

u JSFはコンポーネントベース

u JAX-RSでブラウザの画面を作るにはJavaScriptフレームワークが必要

uどちらにしても、それなりの学習コスト・移行コストがある

95

(C) CASAREAL, Inc. All rights reserved.

Model-View-Controller API (MVC 1.0)

uJava EE 8で導入予定の、HTMLを返すアクションベースフレームワーク

uJAX-RSベース

uURLマッピング、バリデーション、例外処理など、ほとんどJAX-RSの機能を流用している

u詳細は下記の拙著をご参照くださいhttp://www.slideshare.net/masatoshitada7/java-ee-8mvc-10

96

(C) CASAREAL, Inc. All rights reserved.

しかし…

u Java EE 8は2017年上半期リリース予定

u Java EE 7時代の「今」はどうするか?

97

(C) CASAREAL, Inc. All rights reserved.

Jersey MVCとは?

u Jersey独自機能として作られている、HTMLを返すアクションベースフレームワーク

uMVC 1.0に近い

u もちろん相違点は存在する

98

(C) CASAREAL, Inc. All rights reserved.

Java EE 7時代のWeb開発

「第3の選択肢」u Java EE 7時代の今はJersey MVCを使う

uEE 8対応のAPサーバーがリリースされたら、MVC 1.0に移行する

u GlassFishは2017年リリース予定(EE 8と同時)

u 有償サーバーは2019~2020年?

99

(C) CASAREAL, Inc. All rights reserved.

Jersey MVCのライブラリ追加

uGlassFish/Payaraには内包されている

uWebLogicにはJersey MVCの追加が必要

uその他のAPサーバーでは、内包されているJAX-RS実装を無効化して、Jersey + Jersey MVCを追加する

uRESTEasy(WildFly/JBoss内包)には、「REST Easy

HTML Provider」というJersey MVCに似た機能も存在する

100

(C) CASAREAL, Inc. All rights reserved.

Jersey MVCの注意点

uMVC 1.0にはあるが、Jersey MVCには無い機能がある u 逆もまた然り

u作り込み過ぎてMVC 1.0の再発明にならないように注意

u MVC 1.0は今後も仕様が変更される可能性が高い

101

(C) CASAREAL, Inc. All rights reserved.

設定クラス

uResourceConfigを継承し、JspMvcFeatureを登録する

102

@ApplicationPath("api") public class MyApplication extends ResourceConfig { public MyApplication() { register(JspMvcFeature.class); register(MvcBeanValidationFeature.class); property(JspMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/views/"); packages(true, this.getClass().getPackage().getName()); } }

(C) CASAREAL, Inc. All rights reserved.

コントローラークラス

uリソースメソッドでViewableを返す

103

@Path("employees") @RequestScoped public class EmployeeIndexResource { @GET @Path("index") public Viewable index() throws Exception { ... return new Viewable("index"); } }

(C) CASAREAL, Inc. All rights reserved.

JSPファイルの保存場所

(絶対パス指定)

u上記の場合、WEB-INF/views/hoge/fuga/

index.jspにフォワードする

u WEB-INF/viewsは、ResourceConfigサブクラスでJspMvcFeature.TEMPLATE_BASE_PATHで指定した場所

104

package com.example.rest.resource; public class EmployeeIndexResource { @GET @Path("index") public Viewable index() { return new Viewable("/hoge/fuga/index"); } }

(C) CASAREAL, Inc. All rights reserved.

JSPファイルの保存場所

(相対パス指定)

u上記の場合、WEB-INF/views/com/example/

rest/resource/EmployeeIndexResource/index.jspにフォワードする

105

package com.example.rest.resource; public class EmployeeIndexResource { @GET @Path("index") public Viewable index() { return new Viewable("index"); } }

(C) CASAREAL, Inc. All rights reserved.

MVC 1.0のビューの保存場所

u現時点のMVC 1.0の仕様では、Jersey MVCの絶対パス指定が最も近い

u 今のところ、デフォルトでは/WEB-INF/views/配下に置くことしか決まっていない

106

(C) CASAREAL, Inc. All rights reserved.

コントローラーからビューへの 値の受け渡しuMVC 1.0・Jersey MVC両方で利用できることから、

CDI Beanを利用する

107

@Inject EmployeeListDto employeeListDto; @GET @Path("index") public Viewable index() { employeeListDto.setEmployeeList(employeeList); return new Viewable("index"); }

<c:forEach items="${employeeListDto.employeeList}" var="emp"> …

(C) CASAREAL, Inc. All rights reserved.

例外処理はExceptionMapper

u Jersey MVCとMVC 1.0でほぼ同じ

u Viewableのパッケージ名が違うだけ

108

@Provider @ApplicationScoped public class ExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<Exception> { @Inject private ExceptionDto exceptionDto; @Override public Response toResponse(Exception exception) { ... return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(new Viewable("/error/exception")).build(); } }

(C) CASAREAL, Inc. All rights reserved.

バリデーション

uMVC 1.0 → BindingResult u Jersey MVC → @ErrorTemplate

uだいぶ違っていてまだ悩み中なので、近日中にブログ書きます

u 2015 Java EE アドベントカレンダーかも?

109

(C) CASAREAL, Inc. All rights reserved.

日本語情報

uJersey MVCの日本語書籍は無いがブログ情報は多い

u http://qiita.com/opengl-8080/items/f4c25ad671e8a6dac743 など

uブログ情報はやや古いものもあるので(EE 6など)、Jersey公式ドキュメントも読んで最新情報を確認したほうがよい

u https://jersey.java.net/documentation/latest/user-guide.html#mvc

110

(C) CASAREAL, Inc. All rights reserved.

まとめ

111

(C) CASAREAL, Inc. All rights reserved.

Java EE 7時代の「今」は何を選ぶか?

u Java EE 7標準にこだわりたい → JSF

u JavaScriptフレームワークやモバイル連携にこだわりたい → JAX-RS

uアクションベースにこだわりたい → Jersey MVCからMVC 1.0に移行

112

(C) CASAREAL, Inc. All rights reserved.

Enjoy & let’s start Java EE !!

uご参加ありがとうございました!

113