Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Java EEハンズオン資料 JJUG CCC 2015 Fall

20,497 views

Published on

JJUG CCC 2015 FallのJava EEハンズオンの、当日映写するスライド資料です。PDFでダウンロードしていただくことができます。

Published in: Technology
  • Be the first to comment

Java EEハンズオン資料 JJUG CCC 2015 Fall

  1. 1. (C) CASAREAL, Inc. All rights reserved. 脱Struts&独自フレームワーク! 今からでも遅くない Java EE Web開発入門ハンズオン! 株式会社カサレアル 多田真敏 (@suke_masa) JJUG CCC 2015 Fall 2015/11/28(土) 1
  2. 2. (C) CASAREAL, Inc. All rights reserved. このセッションについて u ハッシュタグ
 #ccc_m1 u Java EEのWebアプリケーション開発につ いて、演習を交えながら学習します 2
  3. 3. (C) CASAREAL, Inc. All rights reserved. 自己紹介 u 多田真敏(ただまさとし) u 大阪出身、香川育ちの0x1F歳 u (株)カサレアル所属 u Java EEを中心とした研修トレーナー u JJUG CCCは4回連続4回目の出場 u Twitter:@suke_masa 3 4年前の写真なので実物はもうちょっとおっさん…
  4. 4. (C) CASAREAL, Inc. All rights reserved. 本資料について u 著作権は(株)カサレアルに帰属します。 u 個人の学習、コミュニティや社内の勉強会など、
 「無償の用途」にのみご利用ください。 u 勉強会の場合、会場代など「運営に最低限必要な費用」を参加者 の方から集金する事については「無償の用途」の範囲内とします。 u 本資料を使用して有償のサービスを提供することを禁止 します。また、有償サービスで利用する資料への内容の 転載も禁止します。 4
  5. 5. (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講義
  6. 6. (C) CASAREAL, Inc. All rights reserved. ①Java EEの全体像 6
  7. 7. (C) CASAREAL, Inc. All rights reserved. 背景:Struts 1とSeasar2の終焉 u 2013年 Struts 1.x EOL u 開発ストップは2008年から
 (7年前に終わっていた) u 2016年9月26日 Seasar2 EOL予定 u 2015年9月のSeasar Conferenceで発表
 http://d.hatena.ne.jp/higayasuo/ 20150928/1443415547 7
  8. 8. (C) CASAREAL, Inc. All rights reserved. 背景:脱・独自フレームワーク u 作った社員が異動・退職したら保守できない u 一般に公表されないものなので、
 開発者の教育や外部調達が難しい u 長く使っていて古くなってきた 8 なるべく、世の中で広く使われている 「一般的な」フレームワークが求められている
  9. 9. (C) CASAREAL, Inc. All rights reserved. 現在のトレンド Java EE or Spring Framework u Java EE u 標準仕様=長期的な安定性 u APサーバーも含めたベンダーサポート u Spring Framework u 進化の速さがすごい=Javaの最先端 u 高機能・高生産性 9
  10. 10. (C) CASAREAL, Inc. All rights reserved. なぜJava EEなのか? u 「標準」は「一般的」の最上級 u 最先端ではないが十分に現代的な
 フレームワーク u 最先端が「最善の選択」かは時と場合による u 仕様面・サーバー面での長期的安定性 10
  11. 11. (C) CASAREAL, Inc. All rights reserved. Java EE=フルスタックフレームワーク 11 JSF JAX-RS WebSocket CDI/EJB /JTA JPA Interceptor Bean Validation Servlet/JSP Web ビジネスロジック DBアクセス
  12. 12. (C) CASAREAL, Inc. All rights reserved. Java EE 7対応APサーバー (2015年11月時点) u GlassFish/Payara u WildFly u WebLogic ← 今年10月リリース! u WebSphere u Cosminexus u JBossは来年かも? 12
  13. 13. (C) CASAREAL, Inc. All rights reserved. Java EEは「仕様」 u Javadocを見ると、ほとんどインタフェー ス・アノテーション・例外 u APサーバーは「実装」の集合体 u 細かな挙動は「実装」によって
 異なる部分もあるので注意 13
  14. 14. (C) CASAREAL, Inc. All rights reserved. 今回の環境 u Payara Web ML 4.1.1.154 u GlassFish 4.1.1をベースに、英国C2B2社がバグ修正・ 機能強化を行っているサーバー u GlassFishはJava EEの参照実装 (Reference Implementation : RI) u JDK 8u66 u NetBeans 8.1 (8.0.2でもOK) u JavaDB (Payara内包) 14
  15. 15. (C) CASAREAL, Inc. All rights reserved. 事前準備の確認 u NetBeans・Payara・curlはインストール 済み? u プロジェクトはクローン・ビルド済み? u exerciseブランチに切り替え済み? u アクション項目は表示済み? 15
  16. 16. (C) CASAREAL, Inc. All rights reserved. 今回の課題 u 架空の社員管理システム u 社員データの検索・追加・更新・削除を行う u 同じシステムをJSF/JAX-RS/Jersey MVCと いう違う技術で実装します u これからデモします 16
  17. 17. (C) CASAREAL, Inc. All rights reserved. ②JSF講義・演習 17
  18. 18. (C) CASAREAL, Inc. All rights reserved. JSF (JavaServer Faces)とは? u HTMLを返すWebフレームワーク u コンポーネントベース u .NET、Android、Swing、JavaFXなどのGUIアプ リ経験がある人は馴染みやすい u Strutsなどのアクションベースフレムーワークか ら移行する人は、最初は違和感があるかも 18
  19. 19. (C) CASAREAL, Inc. All rights reserved. JSF実装 u Mojarra (RI) u GlassFish/Payara/WebLogic/WildFly/JBoss内包 u 読み方は「モハラ」 u Apache MyFaces u WebSphere内包 19
  20. 20. (C) CASAREAL, Inc. All rights reserved. JSFアプリの最小構成 u Backing Bean(Javaクラス) u Facelets(画面) u web.xml(設定ファイル) 20
  21. 21. (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"; } }
  22. 22. (C) CASAREAL, Inc. All rights reserved. Facelets u XHTML形式のビュー技術 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="検索">
  23. 23. (C) CASAREAL, Inc. All rights reserved. web.xml u FacesServletの登録が必要 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>
  24. 24. (C) CASAREAL, Inc. All rights reserved. Backing Beanの作り方① 名前付けアノテーションをクラスに付加 u EL式でビューから 呼び出す際の名前 を付ける u デフォルトはクラス 名の頭文字を小文字 にしたもの 24 // 下記の3つは全て同じ意味 @Named public class EmpBean { … } @Named("empBean") public class EmpBean { … } @Named(value = "empBean") public class EmpBean { … }
  25. 25. (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 { … }
  26. 26. (C) CASAREAL, Inc. All rights reserved. ★演習★ Backing Beanの作成 u 演習1-1:Backing Beanクラスに@Named と@ViewScopedを付加する 26
  27. 27. (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; } }
  28. 28. (C) CASAREAL, Inc. All rights reserved. Backing Beanの作り方④ アクションメソッド u ボタンが押された際の処理 を記述する u 画面からはEL式で紐付けら れる u Stringでフォワード先の ビュー名を返す u voidまたはnullの場合、現在 と同じ画面に遷移する 28 @Named @ViewScoped public class EmpBean { @Inject BizLogic logic; public String find() { logic.doSomething(); return "index.xhtml"; } }
  29. 29. (C) CASAREAL, Inc. All rights reserved. ★演習★ Backing Beanの作成 u 演習1-2:アクションメソッドの中身を実 装する u 検索のキーワードを受け取るnameフィー ルド、そのsetter/getterは作成済み 29
  30. 30. (C) CASAREAL, Inc. All rights reserved. 画面の作り方① JSFタグによる記述 u namespaceを指定 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="検索">
  31. 31. (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"; } }
  32. 32. (C) CASAREAL, Inc. All rights reserved. ★演習★ 社員一覧画面の作成 u 演習1-3:ボタンが押された際のアクションメソッドをEL式 で指定する u 演習1-4:tableに社員リストを一覧表示する u ここまで出来たら実行してみましょう u (1)プロジェクトを右クリック→[消去してビルド] u (2)プロジェクトを右クリック→[実行] u Windows PCの方は、セキュリティ警告が出たら[許可]して ください 32 ※データベースが DROP-CREATE-INSERT されます
  33. 33. (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; … }
  34. 34. (C) CASAREAL, Inc. All rights reserved. 【参考】HTML5 Friendly Markup u JSF 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}" />
  35. 35. (C) CASAREAL, Inc. All rights reserved. Bean Validation u Backing Beanの フィールドに @NotNullなどの アノテーション を付ける 35 @Named @ViewScoped public class EmpBean { @NotNull @Size(min = 1, max = 10) @Pattern(regexp = "[a-zA-Z]*") private String name; … }
  36. 36. (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
  37. 37. (C) CASAREAL, Inc. All rights reserved. エラーメッセージの指定 u クラスパスルートの ValidationMessages.propertiesに記述する u メッセージのキーはアノテーションのmessage 属性に{}付きで指定する 37 @Named @ViewScoped public class EmpBean { @NotNull(message = "{message.notnull}") private String name; …
  38. 38. (C) CASAREAL, Inc. All rights reserved. ★演習★ バリデーション u 演習2-1:Backing Beanのnameプロパ ティに検証アノテーションを追加 38
  39. 39. (C) CASAREAL, Inc. All rights reserved. 画面にエラーメッセージを表示 u h:messagesタグで表示する 39 <h:messages id="error" errorStyle="color:red" /> Facelets ブラウザ
  40. 40. (C) CASAREAL, Inc. All rights reserved. ★演習★ バリデーション u 演習2-2:画面にエラーメッセージ表示のタ グを追加する u ここまで出来たら実行してみましょう u (1)プロジェクトを右クリック→[消去してビル ド] u (2)プロジェクトを右クリック→[実行] 40 ※データベースが DROP-CREATE-INSERT されます
  41. 41. (C) CASAREAL, Inc. All rights reserved. 【補足】発展的なバリデーション u http://yamkazu.hatenablog.com/entry/ 20110206/1296985545 を読むと、Bean Validationを一通り学べます u 複数のアノテーションをまとめて1つのアノテーショ ンにできる u 独自の検証ロジックを持ったアノテーションを自作 できる u 複数のアノテーションをグループ化できる 41
  42. 42. (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
  43. 43. (C) CASAREAL, Inc. All rights reserved. Ajaxの利用 u JavaScriptコード無しでAjaxを利用できる u f:ajaxタグ u execute属性:リクエスト時に送信する値を指 定 u render属性:レスポンスで返ってきた情報を描 画する部分を指定 43
  44. 44. (C) CASAREAL, Inc. All rights reserved. Ajaxの利用 u 通常 u Ajax 44 <h:commandButton action="#{empBean.findByName()}" value="検索" /> <h:commandButton action="#{empBean.findByName()}" value="検索"> <f:ajax execute="@form" render=":employeeList :error"/> </h:commandButton>
  45. 45. (C) CASAREAL, Inc. All rights reserved. ★演習★ 検索のAjax化 u 演習3:<f:ajax>タグで、ボタンが押された 際の挙動をAjaxに変更する u ここまで出来たら実行してみましょう u (1)プロジェクトを右クリック→[消去してビル ド] u (2)プロジェクトを右クリック→[実行] 45 ※データベースが DROP-CREATE-INSERT されます
  46. 46. (C) CASAREAL, Inc. All rights reserved. GET時のクエリパラメータの受け取り u JSFは基本的にすべてPOSTで遷移する u GETでのクエリパラメータ取得はFaceletsに
 下記の記述が必要 46 <h:body> <f:metadata> <f:viewParam id="empId" name="empId" value="#{employeeEditBean.empId}"/> </f:metadata> … クエリ パラメータ名 Backing Bean プロパティ名
  47. 47. (C) CASAREAL, Inc. All rights reserved. ★演習★ クエリパラメータの     受け取り u 演習4-1:Faceletsにf:viewParamタグを 記述する 47
  48. 48. (C) CASAREAL, Inc. All rights reserved. @ConversationScoped (会話スコープ) u 会話の開始から終了まで、そのBacking Beanは生存している u 登録→確認→完了のような、複数画面で 値を受け渡す際に有用 u 画面にhiddenタグを埋め込んで値をやりとりす るなどの必要なし 48
  49. 49. (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"; } } u Conversationを @InjectでDI u begin()で会話開 始 u end()で会話終了
  50. 50. (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 されます
  51. 51. (C) CASAREAL, Inc. All rights reserved. 日本語書籍について u Begining 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
  52. 52. (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
  53. 53. (C) CASAREAL, Inc. All rights reserved. ③JAX-RS 講義・演習 53
  54. 54. (C) CASAREAL, Inc. All rights reserved. JAX-RSとは? u JSONやXMLをレスポンスする
 REST Webサービス開発のフレームワーク u シンプルで分かりやすいAPIが特徴 54
  55. 55. (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", … }
  56. 56. (C) CASAREAL, Inc. All rights reserved. なぜREST Webサービスなのか? u クライアントの多様化 u PCブラウザ、スマホ・タブレット(ネイティブアプ リ・ブラウザ)、別システムとの連携… u サーバー側はJSONだけ返して、画面表示はク ライアントに任せる u ブラウザの場合は、AngularJSなどのJavaScript フレームワークを併用することが一般的 56
  57. 57. (C) CASAREAL, Inc. All rights reserved. JAX-RS実装 u Jersey u GlassFish/Payara/WebLogic内包 u RESTEasy u WildFly/JBoss内包 u Apache CXF u WebSphere内包(JAX-WS兼用) 57
  58. 58. (C) CASAREAL, Inc. All rights reserved. JAX-RSアプリの最小構成 u Applicationサブクラス(Javaクラス) u リソースクラス(Javaクラス) u 設定ファイルは必要なし 58
  59. 59. (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 }
  60. 60. (C) CASAREAL, Inc. All rights reserved. ★演習★ Applicationサブクラス     の作成 u 演習1-1:Applicationサブクラスの作成 u クラス内にgetProperties()というメソッ ドがありますが、意味は後ほど説明しま す 60
  61. 61. (C) CASAREAL, Inc. All rights reserved. リソースクラス u @Path+@GETでURLマッピングを指定 u @PathParamでパス内のパラメータを取得 61
  62. 62. (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
  63. 63. (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) { …
  64. 64. (C) CASAREAL, Inc. All rights reserved. ★演習★ リソースクラスの作成 u 演習1-2:クラスに@Pathを付加する u 演習1-3:メソッドに@GET、@Path、 @Producesを付加する u 演習1-4:メソッドの引数に@PathParam を付加する 64
  65. 65. (C) CASAREAL, Inc. All rights reserved. リソースメソッドの戻り値 u HTTPステータスコードと、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化
  66. 66. (C) CASAREAL, Inc. All rights reserved. ★演習★ リソースクラスの作成 u 演習1-5:メソッドの戻り値を記述する u ここまで出来たら実行してみましょう u (1)プロジェクトを右クリック→[消去してビルド] u (2)プロジェクトを右クリック→[実行] u (3) コメント内のcurlコマンドをコマンドプロン プトで実行 66 ※データベースが  DROP-CREATE-INSERTされます
  67. 67. (C) CASAREAL, Inc. All rights reserved. 【補足】MessageBodyWriter u リソースメソッドの戻り値に渡されたオブ ジェクトを、JSONやXMLに変換する役割を 持つインターフェイス u オブジェクトの型・@Producesで指定され た形式・Acceptリクエストヘッダで、どの MessageBodyWriter実装クラスが動くかが 自動的に判断される 67
  68. 68. (C) CASAREAL, Inc. All rights reserved. 【補足】JSONパーサー u MessageBodyWriter内で使われる、オブ ジェクトをJSONに変換するライブラリ u Payara/GlassFishには「MOXy(デフォル ト)」「Jackson」「Jettison」が内包 u 今回はMOXyを無効化してJacksonを有効 化しています 68
  69. 69. (C) CASAREAL, Inc. All rights reserved. 【補足】MOXyの無効化 u Applicationサブクラス内で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; } }
  70. 70. (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; } }
  71. 71. (C) CASAREAL, Inc. All rights reserved. 【補足】JAX-RSの例外 u HTTPステータスコードを表す例外が用意され ている(下記は一部) u WebApplicationException u ClientErrorException (4xx) u BadRequestException (400) u NotFoundException (404) u ServerErrorException (5xx) u InternalServerErrorException (500) 71
  72. 72. (C) CASAREAL, Inc. All rights reserved. 【補足】例外処理 u ExceptionMapperインターフェイスを実装した クラスに、@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(); } }
  73. 73. (C) CASAREAL, Inc. All rights reserved. クエリパラメータの取得 u @QueryParamで取得 u @DefaultValueで、そのクエリパラメータが無 かった場合のデフォルト値を指定可能 73 @GET @Produces(MediaType.APPLICATION_JSON) public Response findByName( @QueryParam("name") @DefaultValue("") String name) { … }
  74. 74. (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) { … }
  75. 75. (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  されます
  76. 76. (C) CASAREAL, Inc. All rights reserved. 【補足】検証エラー時は例外が発生 u ConstraintViolationExceptionが発生する u この例外に対応したExceptionMapperを作って おく必要がある 76 @Provider public class ConstraintViolationExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<ConstraintViolationException> { @Override public Response toResponse(ConstraintViolationException exception) { … } }
  77. 77. (C) CASAREAL, Inc. All rights reserved. 【補足】本セッションにおける 異常時のステータスコード u ID検索→該当IDなしは404、
     IDに数字以外が来ても404 u 複数件検索→検索結果0件の場合、
       200で空のJSON配列を返す u バリデーションエラー→400 77
  78. 78. (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
  79. 79. (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) { …
  80. 80. (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
  81. 81. (C) CASAREAL, Inc. All rights reserved. ★演習★ POSTによる追加 u 演習3-1:リクエストのContent-Typeを MediaType.APPLICATION_JSONに指定する u @POSTは付加済み 81
  82. 82. (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-Zs]*") 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) { …
  83. 83. (C) CASAREAL, Inc. All rights reserved. レスポンス u 201 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(); }
  84. 84. (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  されます
  85. 85. (C) CASAREAL, Inc. All rights reserved. 【補足】MessageBodyReader u リクエストから受け取ったJSONやXML を、リソースメソッドの引数の型に変換 する役割を持つインターフェイス u 引数の型と@Consumesで指定された形式 で、どのMessageBodyReader実装クラス が動くかが自動的に判断される 85
  86. 86. (C) CASAREAL, Inc. All rights reserved. 【補足】Formクラス・DTOクラス・ Entityクラスは分ける u 持つべきフィールド・従うべき規約・付 加すべきアノテーションが異なるので、 似たクラスだが分けたほうが良い u Form → Bean Validation u DTO → JSON, JAXB u Entity → JPA 86
  87. 87. (C) CASAREAL, Inc. All rights reserved. PUTによる更新 u メソッドには@PUTと@Consumesを付加 u 更新対象の主キーは@Pathで指定 u 200 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(); }
  88. 88. (C) CASAREAL, Inc. All rights reserved. ★演習★ 更新 u 演習4:更新リソースメソッドの戻り値を記述す る u ここまで出来たら実行してみましょう u (1)プロジェクトを右クリック→[消去してビルド] u (2)プロジェクトを右クリック→[実行] u (3) コメント内のcurlコマンドをコマンドプロンプト で実行 88 ※データベースが  DROP-CREATE-INSERTされます
  89. 89. (C) CASAREAL, Inc. All rights reserved. DELETEによる削除 u メソッドには@DELETEを付加 u 更新対象の主キーは@Pathで指定 u 204 NO CONTENTとlocationヘッダを返す 89 @DELETE @Path("{id}") public Response delete(@PathParam("id") Integer id) { … URI location = uriInfo.getAbsolutePath(); return Response.noContent() .location(location).build(); }
  90. 90. (C) CASAREAL, Inc. All rights reserved. ★演習★ 削除 u 演習5:削除リソースメソッドの戻り値を記述す る u ここまで出来たら実行してみましょう u (1)プロジェクトを右クリック→[消去してビルド] u (2)プロジェクトを右クリック→[実行] u (3) コメント内のcurlコマンドをコマンドプロンプト で実行 90 ※データベースが  DROP-CREATE-INSERTされます
  91. 91. (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
  92. 92. (C) CASAREAL, Inc. All rights reserved. 日本語書籍について u Web API : The Good Parts u JAX-RSの本ではないが、RESTの基礎 として知っておいたほうが良いこと が満載 u URLをどのように設計するか、異常 時にどのようなレスポンスを返すか など 92
  93. 93. (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
  94. 94. (C) CASAREAL, Inc. All rights reserved. ④Jersey MVC + MVC 1.0 講義 94
  95. 95. (C) CASAREAL, Inc. All rights reserved. JSF・JAX-RSはStrutsから移行しづらい? u JSFはコンポーネントベース u JAX-RSでブラウザの画面を作るには JavaScriptフレームワークが必要 u どちらにしても、それなりの学習コスト・ 移行コストがある 95
  96. 96. (C) CASAREAL, Inc. All rights reserved. Model-View-Controller API (MVC 1.0) u Java EE 8で導入予定の、
 HTMLを返すアクションベースフレームワーク u JAX-RSベース u URLマッピング、バリデーション、例外処理な ど、ほとんどJAX-RSの機能を流用している u 詳細は下記の拙著をご参照ください
 http://www.slideshare.net/masatoshitada7/java-ee-8mvc-10 96
  97. 97. (C) CASAREAL, Inc. All rights reserved. しかし… u Java EE 8は2017年上半期リリース予定 u Java EE 7時代の「今」はどうするか? 97
  98. 98. (C) CASAREAL, Inc. All rights reserved. Jersey MVCとは? u Jersey独自機能として作られている、
 HTMLを返すアクションベースフレーム ワーク u MVC 1.0に近い u もちろん相違点は存在する 98
  99. 99. (C) CASAREAL, Inc. All rights reserved. Java EE 7時代のWeb開発 「第3の選択肢」 u Java EE 7時代の今はJersey MVCを使う u EE 8対応のAPサーバーがリリースされた ら、MVC 1.0に移行する u GlassFishは2017年リリース予定(EE 8と同時) u 有償サーバーは2019∼2020年? 99
  100. 100. (C) CASAREAL, Inc. All rights reserved. Jersey MVCのライブラリ追加 u GlassFish/Payaraには内包されている u WebLogicにはJersey MVCの追加が必要 u その他のAPサーバーでは、内包されているJAX-RS実 装を無効化して、Jersey + Jersey MVCを追加する u RESTEasy(WildFly/JBoss内包)には、「REST Easy HTML Provider」というJersey MVCに似た機能も存 在する 100
  101. 101. (C) CASAREAL, Inc. All rights reserved. Jersey MVCの注意点 u MVC 1.0にはあるが、Jersey MVCには無い 機能がある u 逆もまた然り u 作り込み過ぎてMVC 1.0の再発明にならな いように注意 u MVC 1.0は今後も仕様が変更される可能性が高い 101
  102. 102. (C) CASAREAL, Inc. All rights reserved. 設定クラス u ResourceConfigを継承し、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()); } }
  103. 103. (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"); } }
  104. 104. (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"); } }
  105. 105. (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"); } }
  106. 106. (C) CASAREAL, Inc. All rights reserved. MVC 1.0のビューの保存場所 u 現時点のMVC 1.0の仕様では、
 Jersey MVCの絶対パス指定が最も近い u 今のところ、デフォルトでは/WEB-INF/views/ 配下に置くことしか決まっていない 106
  107. 107. (C) CASAREAL, Inc. All rights reserved. コントローラーからビューへの 値の受け渡し u MVC 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"> …
  108. 108. (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(); } }
  109. 109. (C) CASAREAL, Inc. All rights reserved. バリデーション u MVC 1.0 → BindingResult u Jersey MVC → @ErrorTemplate u だいぶ違っていてまだ悩み中なので、
 近日中にブログ書きます u 2015 Java EE アドベントカレンダーかも? 109
  110. 110. (C) CASAREAL, Inc. All rights reserved. 日本語情報 u Jersey 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
  111. 111. (C) CASAREAL, Inc. All rights reserved. まとめ 111
  112. 112. (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
  113. 113. (C) CASAREAL, Inc. All rights reserved. Enjoy & let’s start Java EE !! u ご参加ありがとうございました! 113

×