開発者: Java
  ダウンロード
Oracle TopLink
Oracle JDeveloper 10g & ADF

  タグ
java adf すべて

Oracle ADFの学習: ビギナーの体験談


Tom Moore著

このケース・スタディでは、Oracle ADFを使用したUI開発について簡潔かつ詳細に紹介します。

2006年11月公開

私が勤務しているウィスコンシン大学オークレア校では、最近、COBOLで書かれ、Unisysメインフレーム上で動作するレガシー・ システムの一部をJava/J2EE環境へ移植しました。 当校のITチームは、主にEclipse、Tomcat、Springなどのオープン・ソース・ツールを使用してアプリケーションを作成しています。 ライセンス機会の変更により、Oracleツールの使用を考慮できるようになったため、Oracle JDeveloper 10gおよびOracle Application Development Framework(Oracle ADF)を使用して、開発モデルをテストするためのアプリ ケーションを作成しました。 ここでは、このアプリケーションについて説明し、Oracle ADFを使用したUI開発の簡潔かつ詳細な概要を提供します。 (技術情報の詳細については、Oracle Technology NetworkのOracle ADF TutorialおよびOracle ADF Developer's GuideOracle Magazineに掲載されたOracle ACEであるSteve Muench氏によるOracle ADFに関する優れたコラム記事、およびOracle JDeveloper discussion forumを参照してください。)

アプリケーションの構築に必要なすべてのステップをここで説明するわけではありませんが、読者が独自の決断を下すために十分な情報が含 まれていると考えます。 前提となるのは、Javaを十分に理解しており、EclipseまたはOracle JDeveloperに精通し、一般的なプログラマとしての知識があることです。 (各ステップの後ではSave Allを 指示しません。)

既存のアーキテクチャと開発モデルを切り替えることは、常に大変なことです。そこで、Oracle JDeveloperとOracle ADFへの変更を正当化するだけの価値を見出した背景について最初に説明します。 また、別の項に"Tips and Gotchas"を記載します。

背景

当校の現在のアプリケーションは、Java(JDK 1.5)、Spring(MVC、Web Flow、JDBC Template)およびJSPページを使用した単純なものです。 データは、Oracle Database 10g Release 2データベースへ複製されています。 オブジェクト・リレーショナル・マッピング(ORM)ツールとしてJBoss Hibernateを使用した経験がありますが、当校のデータ・アクセスは複雑でも動的でもないため、Spring JDBC Templateでも十分にニーズを満たしています。

Oracle Database 10g Release 2を本番環境で使用しているため、データへの簡単なアクセス方法を把握しているOracle Databaseのフリー・スターター・エディションであるOracle Database 10g Express Edition(Oracle Database XE)をWindowsベースのトライアルで使用することになりました。 本番アプリケーションの基礎として、異なるデータソースへマッピングを簡単に移植できるように、オラクルのOracle TopLink ORMツールをテスト・ケースとして使用することが決定していたため、Oracleデータベースを使用するのも当然のことでした。 Oracle Database XEに加えた唯一の変更は、メモリの使用量が減るようにシステム・ホームページからシステム・グローバル領域(SGA)を変更したことです。

Oracle TopLinkを選択したことには、期待した以上の利点がありました。JDBCやSpringのJDBC Templateのようなインタフェースを使用することによる数々の面倒が取り除かれたためです。 (複雑なSpring環境を構成することなくJDBC Templateを使用する例については、Dustin Marx氏が著した『Add Some Spring to Your JDBC Programming』をOTNで参照できます。) JBoss Hibernateは優れたORMツールですが、Oracle TopLinkマッピングをエンドツーエンドのOracle ADFソリューションに統合する機能は驚くほどに生産的であることが証明されました。 

オラクルが推奨するように、データベースへのアクセスをカプセル化するために、当校はEJB Session Beanを作成しました。 必要に応じてビジネス・ロジックを採用できるレイヤーをアプリケーションとデータベースの間に持つことだけが理にかなっています。 セッション・ファサードのデザイン・パターンの使用で典型的なように、当校のアプリケーションには状態を要求するものは今までのところありません。

Oracle ADFを使用する標準的な手順は、データ・リポジトリへのアクセスを提供する一連のデータ・コントロールを作成することで、私たちもこの手順を実行しまし た。 問合せや、ときには更新や削除をおこなうケースのような、ビジネス・ロジックが必要とされない環境では、UIコントロールから直接情報にアクセスすること は非常に生産的になる可能性があります。 より複雑なケースでは、Session Beanメソッドで実装を含めることによってビジネス・ルールを適用できます。 (『Oracle ADF Developer's Guide』 の1.1で、Oracle ADFとJSFを連動し生産的な開発環境を提供する方法について的確に説明しています。)

また、標準JSFナビゲーションを使用して一連のjspxファイルを作成しました。 当校にはStrutsを使用した経験もありますが、今回は使用しないことにしました。オラクルが推奨するjspxファイルを使用しました。

Oracle JDeveloper 10.1.3は、プロジェクト全体を通して当校のIDEでした。 これは当然のように思われますが、言及しないと、Oracle ADFアプリケーションの構築においてOracle JDeveloperが果たす基本的な役割に気づかないことになります。 Oracle JDeveloperはJava開発ツールですが、Oracle TopLinkの機能、Oracle ADF UIおよびデータ・アクセス制御、JSF機能、XMLおよびJSPファイルへのエンドツーエンドのアクセス、それにテスト開発およびデータベース・アクセ ス環境も提供します。

Oracle JDeveloperでファイルを編集すると、Eclipseや他のIDEでは通常見られない程度に、ウィンドウの協調的な同時変化が自動的に発生しま す。 これらの変化によって、さまざまなビューや編集アプローチが提供されるため、Oracle JDeveloperの豊富な機能の使い方は多少覚えにくいことがあります。 ダブルクリックする位置、StructureおよびData Controlウィンドウを使用するタイミング、プロパティ・エディタで値を設定するタイミング、それに場合によってはSourceウィンドウを使用する タイミングやJavaまたはJSPコードを書くタイミングについて学ぶ必要があります。

プロジェクト

当校のプロジェクトは、学生組織のための単純な銀行口座です。 必要とされる基本的な機能は、支出と預け入れの入力および編集です。 このプロジェクトは全般的に『Oracle ADF Tutorial』に説明されている機能のサブセットであるため、SRDemoに精通している人はその要素の多くに見覚えがあることでしょう。 SRDemoは完全なサンプル・アプリケーションで、Oracle JDeveloperのHelpプルダウン・メニューの"Check-for-update"メカニズムからダウンロードできます。 また、完全なソース・コードを含んでおり、『Oracle ADF Developer's Guide』ではOracle ADFを用いた開発方法の説明にそのソース・コードを使用しています。

フェーズ0: アプリケーション構築のための初期設定

ステップ1: JSF、EJBおよびOracle TopLinkテンプレートを用いた新しいWebアプリケーションの作成。 (『Oracle ADF Tutorial』の1-10も参照してください。) テンプレートの選択は重要ではありません。オプションは、たとえ最初に選択しなくても、すべて使用できます。 このテンプレートによって、標準的なModelおよびViewControllerプロジェクトが作成され、アプリケーションのバックエンドおよびフロン トエンドが保存されます。 Javaクラスが作成されるときにOracle JDeveloperのデフォルトとして使用されるため、デフォルトのパッケージ名の設定は重要です。

ステップ2: データベースの設定。 New GalleryのDatabase TierでOffline Database Objectsを試したいところですが、以前に3つの表のセットを用いてスキーマを作成するのに必要なSQLを作成していました。 Oracle Database XE Webインタフェースにログインし、SQL Commandページの参照にあるスクリプトを使用してユーザーおよび表を作成しました。 Oracle TopLinkが十分な情報を得て、より複雑なマッピングを生成できるように、少なくともこれらの表の主キーを指定することが重要です。
  • Accountは、アカウントに関する基本情報を保存します。
  • Detailsは、すべてのアカウントのトランザクション情報に使用されます。
  • Managerは、アカウントに関連する個人のリストです。

表を移入するために、DBUnitを使用するJavaアプリケーションを記述し、参照にあるデータ・セットを使用して CampusAccounts.xmlファイルを作成しました。 XML要素をコピーしてデータ・セットを拡張することもできます。 これはアプリケーションで最初のJavaクラスだったため、パッケージが作成されるように、ModelプロジェクトでNew→General→Javaク ラスの作成を選択しました。 そして、クラスのボディがコピーされ、新しく作成されたクラスに貼り付けられました。 すでにクラスが作成されていた場合は、FileからImportオプションを選択してJava SourceをModelプロジェクトにコピーしていたでしょう。

public static void main(String[] argv) throws Exception {
Class driverClass = Class.forName("oracle.jdbc.OracleDriver");
Connection jdbcConnection =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE",
"CampusAccounts", "xxxxxx");
IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);

IDataSet dataSet = new FlatXmlDataSet(new File("c:\\CampusAccounts.xml"));

try {
DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
}
finally {
connection.close();
}
}
主要部には、DBUnit機能の利用がいかに簡単であるかが説明されています。 Oracle Database XEデータベースへの接続に必要なURLが、標準Oracle JDBCドライバの名前として示されています。

ただし、コードがコンパイルできるように、DBUnitのjarファイルおよびライブラリをプロジェクトへ追加する必要があります。 最初に、DBUnitのZIPファイルからjarファイルを抽出する必要があります(ダ ウンロード)。 Modelプロジェクトの「Properties」→「Libraries」 →「Add Jar」を選択し、DBUnitのjarファイルをプロジェクトへ追加します。 Modelの「Properties」 →「Libraries」→「Add Library」を選択することにより、Oracle JDBC Libraryを追加できます。これには、Oracle JDBCドライバが含まれます。 jarファイルおよびライブラリが使用可能になったら、Oracle JDeveloperのAlt-Enterコード完了オプションを使用して、必要なインポートを自動的に追加できます。 (必ず「java.sql.Connection」 をインポートしてください。)このJavaアプリケーションを実行するには、Applicationsウィンドウのファイルと緑色の矢印を選択します。 一度接続が作成されたら(次のステップで行います)、操作は簡単です。

フェーズ1: 初期モデルの作成

ステップ3: スキーマ作成後のOracle TopLinkオブジェクト・リレーショナル・マッピングの作成。 (『Oracle ADF Tutorial』の1-8および2-2も参照してください。) Oracle TopLinkを使用する前に、接続を作成する必要があります。 ウィンドウが開いていない場合は、「View」→「Connection Navigator」を選択します。 「New Connection on Database」 を選択して名前を入力し、Oracle(JDBC)タイプが選択されていることを確認します。 スキーマ名とパスワードを入力します。 Oracle Database XEを使用している場合は、SIDをXEに変更します。 接続をテストして、成功することを確認します。

Applicationsウィンドウに戻り、「Model」を右クリックして「Tables」 →「New」→「Business Tier」→「TopLink」 →「Java Objects」を選択します。 必要な場合は、マップに名前を付け、接続を変更します。 ステップ2のスキーマを問い合わせ、すべての表を移動します。 パッケージ名を確認します。 指定するパッケージに、一連のデータ・アクセス・オブジェクト(DAO)が各表に対して1つ作成されます。 ModelのOracle TopLinkフォルダのマップを開くことにより、各スキーマ表に対するフィールド・マッピングを表示できます。 Structureウィ ンドウで表を選択した場合は、Mapウィンドウが異なるビューのマッピングを示すように変化します。 このようなことを試してみるのは良い練習になります。これによって、Oracle JDeveloperがウィンドウの変化を調整する方法に慣れることができるからです。

Detailマップで「Queries」タブを選択すると、各 表に対しOracle TopLinkによってfindAllクエリーが自動的に作成されることがわかります。 表の行のより小さなサブセットを生成する単純なクエリーを追加するには、Named Queriesで「Add 」を選択してクエリーに名前を付けます。 次にParametersウィンドウで「Add」を選択し、完全修飾 Javaクラス名(java.lang.Integerなど)を指定し、パラメータ・タイプを設定し、「Name」列 をクリックしてパラメータ名を変更します。 指定する必要のある各パラメータに対して「Add」を選択します。 findAccountTransactionsByAccount()をDetailマッピングに追加し、アカウント番号に基づいて特定のアカウントの 行をすべて取得し、findOneTransaction()をDetailマッピングに追加して、連続番号のペアであるアカウント番号によって区別され る特定のトランザクションを取得しました。次に示すように、findAccountTransactionsByAccount()は ReadAllQueryですが、findOneTransaction()はReadObjectQueryです。

図1

Format」タブを選択すると、Oracle TopLinkエディタを使用してクエリーの作成またはクエリー文字列の入力が行えます。 Query Expression Builderを使用するには、「Expression」→「Edit」を選択し ます。 ビルダーで「Add」を選択して、作成したパラメータに対するSecond Argumentを変更します。 第2パラメータがある場合、再度「Add」を選択すると、次のようにビルダーによっ て自動的にAND節が作成されます。

図2

作成された接続に対応して、デフォルトのOracle TopLinkセッションが作成されます。 「sessions.xml」 ファイルを開き、Structureウィンドウの「Default」を選択してデ フォルトを確認します。 ロギングなどのオプションの変更は非常に容易です。

ステップ4: EJBセッションの作成。 (『Oracle ADF Tutorial』の2-14も参照してください。) 「Model」→「New」 →「Business Tier」→「EJB」→「Session」 Beanを選択します。 Remote Interfaceが必要でない場合以外は、デフォルトが適しています。 Beanの作成を確認すると、表の行で使用できるマージ、維持、リフレッシュおよび削除のメソッドが作成されることが確認できます。 また、作成した名前付きクエリーのそれぞれに対してメソッドが作成されたことも確認できます。 EJBウィザードによって自動的に生成されたJavaコードは、メソッド内でセッション・トランザクションを作成します。 もちろんこのコードは自由に編集でき、既存のメソッドに対するテキストは、これがBeanを再生成する際の設定の場合は上書きされません。

ステップ5: Oracle ADF Data Controlsの作成。 (『Oracle ADF Tutorial』の2-16も参照してください。) Oracle ADF Data Controlsは、前のステップで作成されたSession BeanおよびDAOへのインタフェースを提供します。 データベースにアクセスするユーザー・インタフェース・コントロールを作成するタイミングには、データ・コントロールがグルーを提供します。 「View」 メニューから「Data Control」パレットを開くと、そこは空のはずです。 Session Beanを右クリックし、最後のエントリ「Create Data Control」を選択します。 Data Controlパレットは次を移入します。

図3

プロジェクトの実行可能なバックエンドを作成する初期作業が完了しました。 いくつかのページを構築するまでOracle ADF Controlsなどの生成物の真価は明らかになりませんが、作業にほとんど労力が必要とされないことは驚くべきことです。

フェーズ2: 初期ビューの作成

ステップ6: 初期のfaces-config.xmlファイルでの作業。Web Content」→「WEB-INF」フォルダを開き、アプリケーションを最初に開いたときに作成された「faces-config.xml」 ファイルを開きます。 なんらかの理由でconfigファイルが作成されなかった場合は、「ViewController」プロジェクトを 右クリックし、「New」→「Web Tier」→「JSF」 →「JSF Page Flow & Configuration」を選択します。 faces-config.xmlのデフォルト名は正しいものです。 「Overview」タブを選択すると、次のよ うにconfigファイルの空のビューが表示されます。

図4

このビューは、JSFアプリケーションの中央構成ファイルへの重要なウィンドウです。 Facesアプリケーションでユーザーが1つのページから別のページへ移行する方法を記述する一連のXML要素のほかにも、ユーザーがインタフェース・コ ントロールとやり取りする際に呼び出されるメソッドがあるBean(バッキングBean)のための要素や、ユーザー状態のように長期性の高い情報の格納に 使用されるBeanのための要素があります。

ステップ7: 初期ナビゲーション・マップおよび対応ページの作成。 (『Oracle ADF Tutorial』の3-2も参照してください。) ここで、SRDemoで使用されるページ・テンプレートに基づく一連の初期ページと、ユーザーが1つのページから別のページへ移行する方法を記述する初期 ナビゲーション・ルールが必要になります。 faces-confix.xmlファイルの「Diagram」タブを選 択し、Configurationパレットが開いていることを確認して、「JSF Page」を構成ダイアグラムへドラッグします。 この時点で、構成ファイルにナビゲーション要素が作成されましたが、ページは作成されていません。

タイトルが付いていないページ・アイコンをダブルクリックし、実際にファイルを作成するためのウィザードを開始します。 名前をindexに変更し、ファイルの接尾辞をjspxに変更します(オラクルによる一般的な推奨)。UIコンポーネントがこのページに自動的に公開され ないことを確認して、Oracle ADF Faces Components、JSF Core、Oracle ADF FacesおよびJSF HTMLライブラリへ移動します。 好みのHTMLバージョンを選択します。ここでは、4.0.1 Transitionalでうまくいきました。

index.jspxは、アプリケーションの実際の最初のページへリダイレクトしようとします。これは、Webアプリケーションを作成 するときの標準的な実践です。 悪い前例を作ってしまうかもしれませんが、Sourceウィンドウのindex.jspxへ進み、f:viewタグを次のスクリプトレットに置き換えま す。 ページを管理するためのディレクトリ構造を作成していることに注意してください。administrationはすべてのアプリケーションのページを保存 しますが、campusaccountsというサブディレクトリはこのプロジェクトのページをすべて保存するために使用されます。 スクリプトレットがindex.jspxファイルに挿入されてから、ファイルを安全に保存して閉じます。

<jsp:scriptlet>
response.sendRedirect("faces/administration/welcome.jspx");
</jsp:scriptlet>

Componentパレットから、別のJSFページをfaces-config.xmlダイアグラムへドラッグします。 アイコンをダブルクリックして、そのJSPページを設定するウィザードを開きます。 名前をwelcomeに変更し、ファイル・タイプをjspxに変更します。作成したいサブディレクトリ構造を作成するようにディレクトリを設定してくださ い。 たとえば、当校の場合は、sendRedirectに対応するようにディレクトリを../public_html/administrationに設定し ました。 shuttleオプションは、index.jspxを作成する際に使用したものと同一であり、HTMLバージョンも同一になります。

JSPページへコンテンツを追加するということは、Diagram、Property EditorおよびStructureウィンドウ間の切替えに慣れるということです。 場合によっては、Sourceウィンドウからページを編集することもあります。 Structureウィンドウで、パネル・ページを含む次のテキストに置き換えられるように、faces view要素を開いてデフォルトのf:viewタグを削除します。 パネル・ページは、ヘッダー、ヘルプを選択するためのグローバル・コントロール、フッター、および著作権セクションなどを持つ複合UIコントロールです。 このページを使用すると、標準のインタフェース・コンポーネントを使用して複雑なページを作成することがいかに簡単であるかがよくわかります。 最も簡単にテキストを貼り付ける方法は、Sourceウィンドウへ切り替えることです。ファイルの最初にある3つのJSPタグにカーソルが行くようにして ください。

<f:view>
<f:loadBundle basename="edu.uwec.financial.resources.UIResources"
var="res"/>
<af:document title="#{res['uacct.campusAccounts.title']}"
initialFocusId="start">
<af:form>
<af:panelPage>
<!-- Page Content End -->
<f:facet name="branding">
<af:panelHorizontal>
<af:objectImage source="/images/banner.jpg"/>
</af:panelHorizontal>
</f:facet>
<f:facet name="menu1">
<af:menuTabs var="menuTab" value="#{menuModel.model}">
<f:facet name="nodeStamp">
<af:commandMenuItem text="#{menuTab.label}"
action="#{menuTab.getOutcome}"
rendered="#{menuTab.shown and menuTab.type=='default'}"
disabled="#{menuTab.readOnly}"/>
</f:facet>
</af:menuTabs>
</f:facet>
<f:facet name="menu2">
<af:menuBar/>
</f:facet>
<f:facet name="menuGlobal">
<af:menuButtons>
<af:commandMenuItem text="#{res['uacct.menu.logout']}"
action="GlobalLogout" immediate="true"
icon="../images/blafIcons/logout.gif"/>
<af:commandMenuItem text="#{res['uacct.menu.help']}"
action="GlobalHelp" immediate="true"
icon="../images/blafIcons/help.gif"/>
</af:menuButtons>
</f:facet>
<f:facet name="messages">
<af:messages/>
</f:facet>
<f:facet name="appCopyright">
<!--Copyright msg-->
<h:panelGroup>
<af:objectSpacer width="10" height="10" id="objectSpacer4"/>
<af:panelHorizontal halign="center">
<af:outputText value="#{res['uacct.copyright']}"/>
</af:panelHorizontal>
</h:panelGroup>
</f:facet>
<f:facet name="appAbout">
<!-- The About this Application Link-->
<af:panelHorizontal halign="center">
<af:commandLink text="#{res['uacct.about']}" action="GlobalAbout"
immediate="true"/>
</af:panelHorizontal>
</f:facet>
<f:facet name="infoUser">
<!-- Show the Logged in user -->
<h:outputFormat value="#{res['uacct.connectedUser']}"
rendered="#{userInfo.authenticated}" escape="false">
<f:param value="#{userInfo.userName}"/>
</h:outputFormat>
</f:facet>
</af:panelPage>
</af:form>
</af:document>
</f:view>
Structureウィンドウにエラーが通知されますが、これらは次のステップで解決されます。

ステップ8: 借用の薦め。 (『Oracle ADF Tutorial』の4-2も参照してください。) アプリケーションの作成を 迅速に開始するために、SRDemoからいくつかのファイルを借用することをお薦めします。 リソース・ファイルを使用することが非常に容易なため、すべてのUIコンポーネントのラベル付けにリソース・ファイルを一貫して使用することにしました。Submitの ような一見明白なボタン上のラベルについても使用します。 主としてイントラネットの当校のアプリケーションにi18nの必要性を見込んではいませんが、この設計に決めることによってよい前例が作られます。 ADFUtilsやJSFUtilsなどのクラスは非常に有用なため、これらのクラスを借用することもお薦めします。 JSFおよびOracle ADFフレームワークに格納された変数へJavaコードからアクセスするのは困難です。 Oracleが使用するバインディングおよびネーミングの標準を理解してしまえば、これらのユーティリティ・クラスによってアクセスが非常に簡単になりま す。次に例を示します。 イメージ・フォルダのインポートにも意義があります。イメージ・フォルダには、ブラウザ・ルック・アンド・フィール(BLAF)フォルダやインタフェース で使用されるいくつかのアイコンが含まれるためです。

ここでは、「ViewController」プロジェクトを選択してファイルをインポートし、「File」 →「Import」→「Java Source」へプルダウンして、SRDemoプロジェクトのクラスを参照しました。 SRDemoのフルパスは、myworkと同じレベルにあります。 samples/SRDemo/UserInterface/src/oracle/srdemo/viewを探してください。 utilでADFUtilsおよびJSFUtilsを取得し、パッケージ構造へコピーします(ここでは、srcフォルダの edu/uwec/financial/utilを使用しました)。ResourceAdapterおよびUIResourcesをリソースへコピーしま す(ここでは、edu/uwec/financial/resourcesを使用しました)。MenuItem、MenuModelAdapterおよび MenuTreeModelAdapterをメニューからコピーします(ここでは、edu/uwec/financial/menuを使用しました)。 Javaファイルをインポートする際に、ディレクトリ構造に合うようにパッケージ名を修正しなければならない可能性があります。

File」→「Import」→「Web Source」を選択し、「UserInterface」から「public_html」 を参照してイメージを選択することによって、標準イメージをインポートできます。必ず、イメージ・フォルダをpublic_htmlフォルダへコピーして ください。 このステップは少し困難です。参照をしたときに、簡単に深く進みすぎてしまうからです。

図5

この時点でjspxファイルのエラーは消えたはずですが、brandingファセットに含めるべきイメージなど、解決の必要があるパネ ル・ページの要素があります。 ページのトップに含めたいイメージがある場合は、それをWebContentとしてViewControllerプロジェクトのイメージ・フォルダへイン ポートします。 Structureウィンドウのパネル・ページで「branding」→「panelHorizontal」 を選択し、そのオブジェクト・イメージをPropertiesウィンドウでリセットします。 必ず、ページ上のlogoutやhelpなどのアイコンに正しいSourceプロパティがあるようにすることも重要です。 各アイコンおよびPropertyウィンドウのSourceプロパティにある「...」ボタンを選択し、Source ウィンドウのイメージを見つけます。 welcome.jspxのloadBundleタグのようなエントリを、パッケージ構造に合うように編集する必要があります。

サンプル・プロパティのファイル・エントリは、welcome.jspxで参照されるプロパティとは一致しません。次に、ここで追加し たスターターの名前と値ペアのセットを示します。

uacct.about=About MyBlugold
uacct.copyright=\u00a9 2006 University of Wisconsin - Eau Claire
uacct.menu.help=Help
uacct.menu.logout=Logout
uacct.menu.campusAccounts=Campus Accounts
uacct.campusAccounts.title=Campus Accounts
uacct.connectedUser=Logged in as <b>{0}</b>

ADFUtilsクラスは、ライブラリを必要とするためコンパイルできません。 ViewControllerプロジェクトの「Properties」 を開き、「ADF Model Runtime」ライブラリを追加します。

index.jspx」を選択してアプリケーションを実行すると(緑色の矢印を選択)、次のような画面が表示されま す。もちろん、表示されるのはご自身のバナーです。

図6

ウェルカム・ページにはHelpやLogoutなどのボタンがありますが、これらのボタンはどのページからも選択できるため、本来はよ り"グローバルな"ものです。

ステップ9: メニューの作成。 ここでは、メニューを作成するためにSRDemoから借用したコードについて説明しますが、導入を簡潔に実行したい場合は省略してもかまいません。

トップレベル・メニューの管理に必要なタグおよびJavaコードはプロジェクトに追加されていますが、faces- config.xmlファイルの適切なエントリを追加して接続する必要があります。 通常は、Oracle JDeveloperがエントリを作成するか、または「faces-config.xml」ファイルを開いて「Overview」 タブからBean定義を追加します。 または、マネージドBean要素を(bean commentタグに記されているように)同様のBeanのエントリ・モデルとして使用することによって、Sourceウィンドウ経由で次の例をファイル にコピーします。

<!-- Global menu tab for logout (we also added a tab for help -->
<managed-bean>
<managed-bean-name>menuItem_GlobalLogout</managed-bean-name>
<managed-bean-class>edu.uwec.financial.menu.MenuItem</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>label</property-name>
<value>#{resources['uacct.menu.logout']}</value>
</managed-property>
<managed-property>
<property-name>icon</property-name>
<value>/images/logout.gif</value>
</managed-property>
<managed-property>
<property-name>type</property-name>
<value>global</value>
</managed-property>
<managed-property>
<property-name>viewId</property-name>
<value>/administration/Logout.jsp</value>
</managed-property>
<managed-property>
<property-name>outcome</property-name>
<value>GlobalLogout</value>
</managed-property>
</managed-bean>

<!-- Campus Accounts menu tab (we also added tabs for Purchasing and Accounting) -->
<managed-bean>
<managed-bean-name>menuItem_CampusAccounts</managed-bean-name>
<managed-bean-class>edu.uwec.financial.menu.MenuItem</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>label</property-name>
<value>#{resources['uacct.menu.campusAccounts']}</value>
</managed-property>
<managed-property>
<property-name>viewId</property-name>
<value>/administration/campusaccounts/CampusAccounts.jspx</value>
</managed-property>
<managed-property>
<property-name>outcome</property-name>
<value>GlobalCampusAccounts</value>
</managed-property>
</managed-bean>

<!-- create the main menu menuModel bean, only one needed -->
<managed-bean>
<managed-bean-name>menuModel</managed-bean-name>
<managed-bean-class>edu.uwec.financial.menu.MenuModelAdapter</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>viewIdProperty</property-name>
<value>viewId</value>
</managed-property>
<managed-property>
<property-name>instance</property-name>
<value>#{menuTreeModel.model}</value>
</managed-property>
</managed-bean>

<!-- create the main menu menuTreeModel bean, only one needed -->
<managed-bean>
<managed-bean-name>menuTreeModel</managed-bean-name>
<managed-bean-class>edu.uwec.financial.menu.MenuTreeModelAdapter</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>childProperty</property-name>
<value>children</value>
</managed-property>
<managed-property>
<property-name>listInstance</property-name>
<list-entries>
<value-class>edu.uwec.financial.menu.MenuItem</value-class>
<value>#{menuItem_GlobalLogout}</value>
<value>#{menuItem_GlobalHelp}</value>
<value>#{menuItem_CampusAccounts}</value>
<value>#{menuItem_Purchasing}</value>
<value>#{menuItem_Accounting}</value>
</list-entries>
</managed-property>
</managed-bean>

<managed-bean>
<managed-bean-name>resources</managed-bean-name>
<managed-bean-class>edu.uwec.financial.resources.ResourceAdapter</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>

Beanはリソース・ファイルを参照するため、faces-config.xmlファイルも定義されたエントリを必要とします。 アプリケーション・タグで、(default-render-kitに加えて)次のXML要素を追加します。

<message-bundle>edu.uwec.financial.resources.UIResources</message-bundle>

再び「index.jspx」ファイルを実行すると、次のようなページが表示されます(PurchasingやHelp などのマネージドBeanを追加しなかった場合、ページにはCampus Accountsタブのみが表示されます)。

図7

ステップ10: 最初の入力ページの作成。 最初の"有用な"ページは、口座管理の最初の段階である、ユーザーが口座番号を入力するページです。 「faces-config.xml」 ダイアグラムを開いてそこに新しいページをドロップし、アイコンをダブルクリックしてページを編集します。 当校のケースでは、campusaccountsの組織に別のレベルを作成したかったため、 /administration/campusaccountsにchoose.jspxを作成しました(public htmlの後に\administration\campusaccountsを追加)。 2番目のステップでは、Oracle JDeveloperにマネージドBeanを作成させました。 choose.jspxのバッキングBeanには自動的にChoose.javaという名前が付き、すべてのユーザー・インタフェース・コンポーネント用 のフィールドが含まれます。 これは、スペーサーのように単純なコンポーネントを追加するたびに、コンポーネントはそれ自身のゲッターおよびセッターを持つフィールドとして表示される ことを意味します。 また、Javaコードを書いてスペーサーのプロパティのサイズ(高さなど)を変更したい場合には意義がありますが、複雑なバッキングBeanも作成しま す。 この場合、それが何かを理解したいときは、自動的に作成されたバッキングBeanから始めると簡単です。

Structureウィンドウを使用して、welcome.jspxのviewタグに置き換えます。実質的には、テン プレートとしてウェルカム・ページを使用しています。 choose.jspxのStructureウィンドウでviewタグを削除してから、welcome.jspxのviewタグをコピーして choose.jspxに貼り付けることができます。Sourceウィンドウを変更する場合は、jspxにバッキングBeanがあることを示すHTMLコ メントを残すようにしてください。オラクルの表記規則は次のようなものです。

<!--oracle-jdev-comment:auto-binding-backing-bean-name:backing_administration_campusaccounts_choose-->

GlobalCampusAccountsでインタフェースがアプリケーションの最初のページに移動することを指定するナビゲーショ ン・ルールをFaces構成ファイルに追加します。 これは、グローバル・ルールです。なぜなら、どのアプリケーションのどこからでもそのタブを選択することによってCampusAccountsに変えるこ とができるためです。 faces-config.xmlに入力されるタグは次のとおりです。

<navigation-rule>    
<navigation-case>
<from-outcome>GlobalCampusAccounts
<to-view-id>/administration/campusaccounts/choose.jspx
</navigation-case>
</navigation-rule>

commandMenuItemsでLogoutおよびHomeアイコンのプロパティを編集し、アイコンの値を変更してBLAFフォル ダのGIFファイルを使用する場合があります。

PanelHorizontalをパネル・ページ内へ挿入し、入力テキスト・コンポーネントを保持する必要があります。 通常、これを行うにはStructureページから「PanelPage」要素を右クリックし、「Oracle ADF Faces Core」コンポーネントを選択するのが簡単に思えますが、Componentパレットを使用することでも実行できます。 Oracle ADFフォームはPanelPageを内包するため、すでにHTMLフォーム要素があります。 InputTextコンポーネントを水平パネルへ追加します。 Propertiesウィンドウから、リソース・ファイルに格納されたプロパティを使用するようにラベルを変更します。 簡単な方法は、リソース・ファイルを編集してプロパティを最初に追加する方法です。それからStructureウィンドウの「inputText」 要素をダブルクリックし、「Bind」を選択してJSF Objectsでresを見つけ、入力したばかりのプロパティ値を選択します。 リソースへのアクセスに必要なELフォーマットに慣れてしまえば、Property Editorでプロパティ値を入力することも簡単です。 入力テキストの後にCommandButtonを水平パネルへ追加し、その名前を変更してリソース・ファイルで定義された別のプロパティを使用します。繰 り返しますが、Structureウィンドウを使用することをお薦めします。

ボタンをダブルクリックして、バッキングBeanへ進みます。 InputTextコンポーネントからテキストを取得し、ユーザーがCampusAccountsアプリケーションのオプションにアクセスすると常にそれ を使用できるように、ユーザー状態へ保存する必要があります。

public String commandButton1_action() {
Object text = getInputText1().getValue();

UserSystemState.storeCurrentAcctNum(new Integer(acctNum));

return "list";
}

ここでは、検証を回避しました。Facesコンポーネントのオプションを使用して検証を不要にします。 InputText要素に必要なプロパティを設定した場合、ユーザーは値を入力する必要があります。 InputTextタグ内にValidateRegExpバリデータを挿入してパターン[0-9]+を追加すると、ユーザーは少なくとも口座番号の一桁を 入力するように要求されます。

当校では、SRDemoからUserSystemStateを追加し、それをモデルとして使用して、口座番号を保存する静的関数を作成 しました。 また、faces-config.xmlファイルのマネージドBeanの名前に、userSystemState(uは小文字)を追加する必要もありまし た。 managed-bean-classフィールドから、私たちが使用したパッケージ名を推測できます。 Oracle JDeveloperがfaces-config.xmlファイルを管理する優れた機能の1つは、コードのコンパイルまたはパッケージ名の指定に問題があ る場合は、そのタグに警告が表示されることです。 Oracle JDeveloperは、能動的にXML構成ファイルを解析します。

<managed-bean>
<managed-bean-name>userSystemState</managed-bean-name>
<managed-bean-class>edu.uwec.financial.view.backing.UserSystemState</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

次に、Commandボタンで使用される静的関数を作成するためのUserSystemState の始動コードを示します。これは、SRDemoのすべてのフィールドおよびメソッドを置き換えます。 パッケージ名の確認を忘れないでください。

private HashMap _settings = new HashMap();
private static final String CURRENT_ACCT_NUM = "CURRENT_ACCT_NUM";

public Integer getCurrentAcctNum() {
return (Integer)_settings.get(CURRENT_ACCT_NUM);
}

public void setCurrentAcctNum(Integer acctNum) {
_settings.put(CURRENT_ACCT_NUM, acctNum);
System.out.println("setCurrentAcctNum:"+acctNum); // some old fashioned testing
}

public static void storeCurrentAcctNum(Integer acctNum) {

JSFUtils.setManagedBeanValue("userSystemState.currentAcctNum", acctNum);
}

public static void retrieveCurrentAcctNum() {
JSFUtils.getManagedBeanValue("userSystemState.currentAcctNum");
}

このコードには、少し不思議な部分があります。userSystemState.currentAcctNumは、 UserSystemState内のフィールドへの参照のように見えますが、そのような名前のフィールドはありません。 JSFUtils.getManagedBeanValue関数呼出しへの引数は、ゲッターとして解決されます。したがって、 userSystemState.currentAcctNumは、getCurrentAcctNum()を取得するための呼出しとなります。

index.jspx」を実行して「CampusAccounts」タブを選択すると、次のようなアプ リケーションの最初のページが表示されます。

図8

ステップ11: 最初のOracle ADF Data Controlsの作成。 (『Oracle ADF Tutorial』の5-2も参照してください。) ここからOracle ADFの価値が実際に分かり始め、面白くなってきます。 ユーザーが口座番号を入力できるページを作成したら、次にその番号に関連するすべてのトランザクション、つまりファイル上のすべての支出と預け入れを フェッチします。

facesナビゲーション・ダイアグラムに/administration/campusaccounts/list.jspxという ページを作成し、list.jspxを編集すると自動的にUIコンポーネントが公開されます。ステップ9で実行したように、welcome.jspxから viewタグをコピーします。

リスト・ページを接続して、Detail表(または考え方によってはDetail DAO)から適切な行を表示させる必要があります。 Oracle ADF Data ControlsがOracle ADFアプリケーション構築の中心であることに留意し、「Data Control」パレットを開きます。

図9

findAccountTransactionsByAccount()関数をリスト・ページへドラッグ・アンド・ドロップできます。 この場合、Commandボタンまたはパラメータ・フォームのようなコンポーネントを作成できます。

代わりに、「Detail」をpanelPageへドラッグ・アンド・ドロップし、Detail表から表示できる、共通 の口座番号を持つ一連の行を作成します。 この状況で意味をなすコンポーネントの長いリストがあると仮定して、「Tables」 →「ADF Read-only Table...」を選択します。 Action Binding Editorが表示されたら、口座番号用に格納された値を選択ページから取り出し、それを findAccountTransactionsByAccountで使用される値としてバインドする必要があります。

図10

すべてのフィールドを表示させ、選択およびソートを有効にします。 また、列プロパティを編集し、ソートを選択的に有効化または無効化し、Structureウィンドウの各列をダブルクリックして列ヘッダーを変更できま す。 当校のケースでは、列ヘッダーをリソース・ファイルに追加し、HeaderTextを#{res ['uacct.campusAccounts.account']}のような参照にバインドしました。 (Structureウィンドウのコンポーネントをダブルクリックして、表の選択ファセットのテキストをリセットすることもできます。) Bindボ タンが役立つことがわかりました。

アプリケーションを実行して有効な口座番号を入力すると、次のような画面が表示されます。

図11

ただし、口座番号を1,000件入力した後は、選択ページにとどまったままになります。 そのため、選択ページからリスト・ページへのトランジションを指定する必要があります。 faces-config.xmlファイルで、「Design」 ウィンドウを開き、Componentパレットが表示されていることを確認します。 「JSF Navigation Case」 を選択し、選択ページ、リスト・ページの順にクリックします。 Choose.javaのCommandボタン・アク ションによって返される値に対応して、トランジション・レベルを編集し、successをlistに変更します。すると、データがリスト・ページに表示さ れます。

Detailデータベース表から、エントリを含むこの表を表示させることがいかに簡単かに注目してください。 インタフェース・コンポーネントはOracle ADF JSFコンポーネントであるため、ページ区切り(一致する結果が合計33件の場合、1度に10件を印刷または33行すべてを印刷)、バンド(各行が異なる 色)、ソートなどの機能や、ラジオ・ボタン経由で個々の行を(たとえばそのコンテンツの編集目的で)選択する機能を含む、複雑な表示オブジェクトを無償で 取得できます。 このページのルック・アンド・フィールはデフォルトのOracleスキンを使用していますが、コンポーネント・タグの指定に使用されるCSSファイルを変 更して、色、フォントおよびアイコンを変えることができます。

また、Oracle ADFが提供する高度なデータ・コントロールを使用して問題なくデータにアクセスすることがいかに簡単であったかに注目してください。 Oracle ADF Read-Only表をページの上にドロップしたとき、返されるヘルパー・オブジェクトのタイプ(Detail.java)が推測され、適切な列の作成に 自動的に使用されました。 タイプの解決は元のデータベース表から得られるメタデータに基づくため、行セット動作(1回に10行)が提供されます。

ステップ12: 編集ページの作成。 (『Oracle ADF Tutorial』の10-2も参照してください。) リスト・ページで、選択用のTableファセットにはCommandボ タンを内包するaf:tableSelectOneタグが含まれます。 「Command」ボタンをダブルクリックす ると、バッキングBeanが開かれます。そこでは、データをフェッチしてヘルパー関数を呼び出し、次のページでの検索用に格納できるように、選択された行 を一意に識別できます。

public String commandButton1_action() {
setCurrentTransactionIdFromRow();

return "edit";
}
List.javaのヘルパー関数は次のとおりです。
private void setCurrentTransactionIdFromRow() {
FacesContext ctx = FacesContext.getCurrentInstance();
JUCtrlValueBindingRef tableRowRef = (JUCtrlValueBindingRef) this.getTable1().getRowData();

Integer transId = (Integer)tableRowRef.getRow().getAttribute("cdPostSequence");

UserSystemState.storeCurrentTransId(transId);
}

storeCurrentTransId()は、ステップ9のstoreCurrentAcctNum()をモデルとして使用し、 UserSystemStateに追加する必要があります。

ここまでは、編集する行の選択に必要な変更について説明してきました。 次に、編集が実行される新しいjspxページを作成する必要があります。 faces-config.xmlファイルで、jspページを追加し、名前がedit.jspxになるように編集します。Componentパレットから 「JSF Navigation Case」を選択し、Designウィンドウのトランジション・レベルを変更して、Commandボ タンで指定された戻り値に一致するように編集します。

edit.jspxページに変更し、Data Controlパレットから「findOneTransaction」 →「Detail」を選択して、「Forms」から「ADF Form」のパネル・ペー ジの上へドラッグします。 Submitボタンを含めて、必要な場合はフィールド順序を変更します。 パラメータをJSF Objectsの値に設定し、UserSystemStateからacctNumおよびtransIdを使用します。 アクションのバインディングが完了すると、ユーザーによる編集を望まないフィールドに対して、readOnlyプロパティをtrueに設定できます。 Structureウィンドウの「inputText」フィールドをそれぞれダブルクリックし、リソース・ファイルからラベルを設定しま す。 最初にリソース・ファイルの値を編集するほうが容易です。 ユーザーに編集ページからの取消しを許