Will be translated in English soon. Sorry for inconvenience.
この記事は2014 Java EE Advent Calendarの12月24日分になります。キリスト教徒ではないのですがメリークリスマス。
今年はJava EEに関する大きな発表が無かったのでネタ的に困る訳なのですが、個人的な「温故知新」ブームに乗っかり、こんなのをやってみることにします。
はい、超スタンダードなJava EEの使い方です。勿論、Java EE 7で。残念ながら商用サーバーのEE 7対応はまだですが、来年は対応するという話を聞きますので、今のうちに慣れておきましょうということで。
ただ作るだけでは面白くないので、できるだけ最速でイチから手順を追って作っていくことにします。勿論NetBeansの自動生成機能を駆使します。また、お仕事でもそのまま使えるようなコードで、という制約付きです。Java EEはめんどくさい、という意見を聞きますが、そんなことないよ、という事を証明するべく、こんな挑戦を敢えてクリスマスイブにやってみるわけです。暇人と呼ばないで(笑) ※ほんとは正直忙しすぎて死にそうです
さて、細かい前説は抜きにして、最速で順番にやっていきましょう。
今回の環境です。本番でもそこそこ使えるようなものを選んでみました。OSは何でもOKですね。わたしは普段使いのOS X Yosemiteを・・・と書いていたのですが、前の記事の通り個人PCをWindowsに戻してしまったので、途中まで出来ていたものをWindows 8.1 64-bitで再度やり直しました。Realforce 87Uが快適すぎるので助かりました。
なお、私は普段お仕事でも家庭でも英語環境で使っているのでスクリーンショットや用語は英語ですが、推測できる範囲だと思いますので適当に読み替えて下さいませ。
- JDK: JDK 8 の最新版 (この記事では JDK 8u25)
- IDE: NetBeans 8 の最新版 (この記事ではNetBeans 8.0.2)
- App Server: GlassFish 4 の最新版 (この記事では GlassFish 4.1)
- Database: MySQL 5.6 の最新版 + MySQL Workbench の最新版 (この記事では MySQL 5.6.22)
1. データベース
まともな企業システムをターゲットにしているので、データベースがあって然るべきでしょう。DB処理はJava EEの華です。ここをすっとばしたJEEの説明が多い気がするので、ここに改めてまとめておきます。
エンタープライズ系のプログラマーがデータベースのインストールすら出来ないというのは恥ずべき事なんじゃないかなと思うのですが、何となく日本のWeb系の流行がNoSQLとかBuzz方面に流れがちだ、ということで、特に若手の育成面を危惧しています。地に足をつけて物事を考えたいですね。流行は流行で別途追っかけるとして。
1-1. データベースの準備
こういうのは依存関係の深い場所から作っていくのが正しい在り方です。ですのでまず、データベースからですね。Oracle Databaseが所謂スタンダードかなと思いますが、フリーのXEがOS X用に出ていないので、ここでは涙を呑んでMySQLをインストールします。インストーラーを落としてぽいっと入れれば終わりです。
http://dev.mysql.com/downloads/mysql/
CUIで諸々やるのは面倒なので、MySQL Workbenchも入れてしまいましょう。Windows版だとDeveloper Defaultを選べばいいです。以下Windows版をメインに書きますので、OS XとかLinuxの方はユーザーアカウント等はインストール後にMySQL Workbench等で個別に設定する必要があります。
インストール途中でアカウントを作成します。今回のアプリ用の「Advent」ユーザーを作りましょう。めんどくさいのでパスワードも同じにしましたが、外部から接続されると厄介なので接続元許可をlocalhostに制限しておきましょう。
rootもここで設定しておきましょう。この辺はWindows版便利ですね。
あとはデフォルト値でホイホイ進めれば、最後にMySQL Workbenchが起動します。rootの接続が出来ているので、これをクリックしましょう。
最初にスキーマを作ります。「Create New Schema」を選択します(+の付いたデータベースアイコン)。名前は「advent」でいいですかね。CollationはServer Defaultで良いかと思います。
「Users and Privileges」で「advent」を選択し、(開発用途なので)全権を「Select “ALL”」で選んでおきましょう。終わったらApply。※当然ですが本番運用でこんな事はしないで下さい。
これでadventユーザーがadventスキーマを使えるようになりました。これでこのMySQL Workbenchの役目は終わりです。これ以降はNetBeansで作業することにします。そっちが楽です。
1-2. スキーマの作成
さてNetBeansを起動して、Serversタブを開いて、今回作ったスキーマを接続しましょう。右クリックして「Register MySQL Server」を選択して登録しましょう。接続情報は上の通りですね。分からない方は以下を参考に。
成功したら「advent」の接続が登場します。これでようやく全ての作業開始です。長い・・・
では今回のテーブルを作りましょう。「Advent」スキーマをを開いて、Tablesで右クリックして「Create Table」。以下のような感じで。ぶっちゃけここはお任せなので、めんどくさい人は1カラムでもいいでしょう。
- Customer
- ————-
- CustomerID BIGINT PRIMARY KEY
- Name VARCHAR(100) NOT NULL
- PostalCode VARCAR(10) NOT NULL
- Address VARCHAR(200) NOT NULL
- Phone VARCHAR(30) NOT NULL
- Note VARCHAR(1000)
これでデータベース側は準備完了です。
-
2. サーバーサイドを作成する
さて、ようやくJava EEです。以下の大半の処理はデータベースを以下に効率的に処理するかという観点になってます。これはCOBOLシステムに代表される「コンテナー管理型システム」の現代版としてJava EEが元々設計されていることに由来します。超高額で場所を取るホストシステムが不要であり、家のPCで気軽に無料でプログラミングできるJava EEがある現代は恵まれた世界だなと思います。
今回作成するパッケージはは3つ。CRUDを行うDAOと、ビジネスロジックを記述するLogic、および、データベースの写像としてのEntityです。LogicとDAOをごっちゃにして作る人がいますがやめたほうがいいでしょう。自動生成がメインであり、JPQLやCriteria Queryの記述がメインのDAOはあくまでDAOとして分けておかないと、数年後に破綻する羽目に陥る気がします。
なお、以下NetBeansを使っていますが、一点だけお勧めの設定変更があります。デフォルト設定ではフォントがMonospacedになっていて非常に見辛いので、Courier NewやConsolaなど英字等幅フォントにに変更すると非常に見やすくなります。Tool > Options > Fonts & Colorsからどうぞ。
2-1. サーバーサイドプロジェクトを作成する
NetBeansからプロジェクトの作成で、Maven > Web Application を選択します。ちなみにJava EE 6からWARにEJBを入れられるようになったので、今回もそれを活用します。必ずMavenのプロジェクトを選択して下さい。ここで間違って後で地獄を見る系の人が多いです。もうNetBeansのオリジナルプロジェクトファイルは廃止していいんじゃないかなと思うのですが・・・
プロジェクトは適当に。「advent-jee7」としておきます。
Application ServerにGlassFish Serverを、Java EE Versionには「Java EE Web」を選択します。ちなみにこれはWebプロファイルであり、Fullプロファイルをここで選択できないのはNetBeansのバグですね。
ここで 一旦Finishして、生成されたプロジェクトファイルを手作業で修正します。プロジェクトのProject Files > pom.xmlを開き、「javaee-web-api」を「javaee-api」に変更して保存し、プロジェクトをビルドすれば完了です。
これを・・・
こんな感じに。これでEJBがWAR内でフルに使えるようになります。ここから開始しましょう。
2-2. 自動生成でJPA系クラスを作成する
DB接続系の処理ですが、Java EEだとJPA一択です。元ネタのHibernateと一緒なので、大体誰でも理解できると思いますが、要は「テーブルの1行=Javaクラスの1インスタンス」で処理するだけの単純明快な標準フレームワークです、と書けばいいでしょうか。
業務システム構築では、こういうところをセコセコ手作業してたらやってられないわけですので、Databaseのテーブルからちゃっちゃか自動生成してしまいます。
プロジェクトで「New > Other」から、「Persistence > Entity Classes from Database」を選択し、MySQLの接続を選択して、JNDIデータソース名「jdbc/advent」を指定して、上で作成した「Customer」テーブルを選択します。あとはデフォルト値で進めれば・・・
はい、DB接続設定が含まれたpersistence.xmlと、「Customer」テーブルに対応付いた「Customer」クラスが作成されます。簡単ですね。これぞJava EE。このクラスだけではデータベースにCRUDできませんので、次にDAOを作成します。これをEJBで作るのがポイントです。ここで間違える人が多いですが、選択肢はこれしか無いと思った方が良いのではないでしょうか。
「New > Other」から「Enterprise JavaBeans > Session Beans For Entity Classes」を選択します。
Entity Classesに上で作成したEntityが出てくるので、選択します。
パッケージ名の後ろに「dao」をくっつけてあげましょう。
完了するとEntity Managerを内包した「CustomerFacade.java」という名前のEJBが自動生成されます。これを使ってCRUDするわけです。なお、このEJBは「AbstractFacade」という名前のスーパークラスを継承しており、そこにCRUDの実装がありますので、基本処理を変更したい場合はここをいじります。ただ、二つ目以降のDAOを作成した場合、同じようにこのスーパークラスを継承するように自動生成されるので、注意が必要です。
よく見たらEntityのクラスがプロジェクトパッケージの直下にありました。これは生成時のオプション指定忘れなので「entity」とおしりにくっつけます。各種処理はNetBeansがやってくれます。
2-3. ビジネスロジックを作成する
はい、最後にビジネスロジックです。当然ながらEJBで作ります。
ビジネスロジックは自動生成なんかできないので、普通に作成します。「New > Other」から「Enterprise JavaBeans」、名前に「CustomerLogic」、パッケージを「advent.logic」にして生成。
頭に「@Stateless」と書いてあるだけの普通のPOJOができます。これが今時のEJBですね。単純バンザイ。
さて、とりあえず動かすためにはデータが必要ですので、今回はまずデータ登録系の処理をここに追加しましょう。こんな感じです。ここには普通にDAOクラスを@EJBでインジェクトし、そこで該当メソッドを呼び出すだけになります。
なんというか、拍子抜けですね。データベースを含むトランザクション処理はEJBコンテナー側が全自動でやってくれるので、これが正しい姿です。このメソッドが呼ばれた瞬間にJTAトランザクションが開始(BEGIN)され、正常終了するとトランザクションが完了(COMMIT)されます。例外が発生した場合は取り消し(ROLLBACK)ですね。エンタープライズ系処理はこうでなくてはいけません。COBOLの正統後継者たる所以です。
はい、バックエンド系処理は終わりです。データベース系設定作業がくそめんどくさい割に、バックエンド処理は爆速で終わったかと思います。
-
3. Web画面作成
最後に画面側です。バックエンドを呼び出す画面についても省エネ爆速で作りましょう。作るファイルは三つ。FaceletとBacking Beanは二つでひとつのセットです。あとは完了画面だけ作ります。最低限動く事を確認するだけの構成にします。
3-1. JSFを使うためのプロジェクト設定
NetBeansでMaven WARプロジェクトを作った場合、初期設定でJSFが有効になってません。これでは困るのでちょいと設定します。プロジェクトを右クリックしてFrameworksからJavaServer Facesを選択します。
また、JSFの画面ファイルであるXHTMLが簡単に起動するように、URL Patternも「*.xhtml」に変更しておいて下さい。じゃないと全てのリクエストに対して/faces/とかつけなければならず、実態のファイルの配置とずれてしまうという困ったことがおきます。
JSFを有効にしたら、index.xhtmlファイルができます。こいつが新しいトップページになりますので、古いindex.htmlは削除して下さい。ここまで全自動でやって欲しいなぁ・・・余計な作業ですね。
3-2. Backng Beanの作成
そろそろこれまで作ってきたものを一度動かしてみたい気になりますが、最速を目指すこの投稿ではスキップして、一気にBacking Beanを作ります。ASP.NETのコードビハインドみたいなやつです。画面と一対一で原則作ります。
普通にクラスを新規作成します。アノテーションで@Namedと、@ViewScopedをつけて下さい。要注意なのは、「import javax.faces.view.ViewScoped;」側を使って下さい、ということです。同じ名前のがjavax.faces.beanにもありますが、こちらを使うと動きません(こちらはJava EE 6以前(JSF 2.1以前)用)。
残りはEntityに定義したものをそのままフィールドに定義してしまいましょう。あとはGetterおよびSetterを作る必要がありますが、そんなものはNetBeansに作らせましょう。右クリックして「Insert Codes…」で「Getter and Setter」ですね。日本語版だと妙な名前になってた気がしますが、こういうプログラミング系は英語版を使うと変な所で悩まなくとも済みます。
最後にボタンを押したときのアクションメソッドを作ります。下記のような感じです。Entityに画面の中身を詰めてEJBに投げるだけ。簡単すぎる。
注意点としては、CustomerID列についてはデータベース側で自動採番されるのですが、EntityのBean Validationの関係上、NULLが許容されないため、とりあえずLong.MIN_VALUEを入れておきました。0でも何でもいいんですが、INSERT時に正しい値に置換されますので気にしないで下さい。
ちなみにここでの考慮点としては、「EntityをそのままBacking Beanのフィールドに設定した方が早いのでは?」というFAQがあります。が、分けた方が良いでしょう。画面で入力する値は本質的に全て文字列ですが、DB設定の型は様々です。入力値のチェックも考慮した場合、すべてString型で定義したBacking Beanと、本質的な正しさを追求すべきEntityは分けた方が良いでしょう。
3-3. Faceletの準備
はい、では最後にFaceletをいじくりましょう。index.xhtmlを開きます。
なんというか、丸ごとふるくさい構成になってますので、HTML5にちょいと書き換えて、不要なタグを削り、JSF 2.2で必要となるネームスペースを追加します。こんな感じです。「xmlns:jsf」というのを追加する必要があります。URLそのものはNetBeansが自動補完してくれます。これが無いとJSFの特殊タグが使えないのです。要注意。これもNetBeans側のテンプレートを更新して欲しい気がしてます。自分でContributeしろと云われそうですが。
はい、とりあえず画面側はできましたので、ここで一回起動しておきましょう。メニューバーの右矢印ボタンを押すと、ブラウザーが起動するかと思います。下記の画面が出たら、バックエンド側のEJBやJPAも正常に動作しています。もう9合目です。もう一息。
では最後にBacking Beanと結合していきます。当たり前ですがFaceletでもコード補完が動きますので、ホイホイやっていきましょう。
完成版はこんな感じです。JSF 2.2からはHTML Friendly Tagsといって、ふつうのHTMLに対してjsf:valueやjsf:actionを追加で入れていく感じになっています。これならば誰でもできますね。昔のh:inputTextとかを忘れて思い出せずイライラするといった非生産的な状況とはおさらばです。
注意点としては、form要素に対してjsf:idを(名前は何でも良いので)入れておかないと動かないという点だけでしょうか。まあめんどくさいのでformとか何とか入れておいて下さい。
最後に完了画面も作っておきましょう。index.xhtmlと同じ場所に「thanks.xhtml」をおいて下さい。index.xhtmlをコピーして削るのが良いかと思います。こんな感じ。
終わったらもう一度実行ボタンを押しましょう。うまく行けばこんな画面が出てくるかと思います。
テストをやらねばなので、とりあえず嘘情報をつらつらと・・・
入力してボタンを押したら完了画面が出ておしまいです。そういう作りにしたので・・・
データベースの中身を見てみましょう。正常に登録されてるかな・・・? Servicesタブからcustomerテーブルを開いて、View Data…です。
正常に登録されていました。一発で動いてホッとします(笑)。
はい、これでおしまいです。完了。この記事はスクリーンショット等を取りつつ書きつつやったので2時間ちょい程度かかりましたが、そんなことをしなければここまで最速で10分から30分くらいでしょうか。データベースの設定を一度やっておけば、あとは上記2.以降をやればいいので、10分くらいでできるかな。Java EEも簡単になりましたね。初代J2EE 1.2時代のめんどくささと比較しても、雲泥の差です。最初からこうあってほしかった(笑)。
Java EEのこの安定感は素晴らしいですね。繰り返しになりますが、上記の作業手順や生成方法、生成されたファイル群は、本物のお仕事でもそのまま使えるものです。今回は画面遷移や入力値チェック等は省きましたが、その辺は別記事等でフォローしたいなぁと思っています。
なお、上記のコードについてダウンロード提供しようと思ったんですが、生成されたコード群がアホみたいに小さいので、是非ご自身でやっていただきたいなと考えまして一旦見送ります。自分でタイピングしないと覚えないので、30分時間を作って是非やってみてください。※ご要望があれば上げます。
次回の2014 Java EE Advent CalendarはArshal Ameenさんの記事になります。最終回ですね。