ヘッダーをスキップ
Oracle® Fusion Middleware WebCenter Sites開発者ガイド
11gリリース1 (11.1.1.8.0)
E49681-03
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

72 WEMフレームワーク: アプリケーションの開発

この章の全体を通して「Articles」サンプル・アプリケーションを使用し、RESTコールを実行するアプリケーションの基本アーキテクチャについて説明します。

この章には次の項が含まれます。

72.1 アプリケーションの構造

図72-1は、「Articles」サンプル・アプリケーションのソース構造を示しています。デプロイメント時に、次のディレクトリはソースからターゲットにコピーされます。libディレクトリの内容は/WEB-INF/lib/にコピーされます。resourcesディレクトリの内容は、/WEB-INF/classes/にコピーされます。

図72-1 「Articles」サンプル・アプリケーションのソース構造

図72-1の説明が続きます
「図72-1 「Articles」サンプル・アプリケーションのソース構造」の説明

「Articles」は、Spring MVCで開発されたJava Webアプリケーションです。次のページが提供されます。

72.2 構成ファイル

ソース・ファイル

/sample app/articles/src/main/java/

/sample/フォルダには、次に示すソース・ファイルが含まれます。

インストーラのリソース

/sample app/articles/src/main/resources/install

/install/フォルダには次のリソースが含まれます。これらのリソースはホーム・ページを構成する際に、InstallControllerで使用されます(図72-3)。

ホーム・ページ・ファイル

/sample app/articles/src/main/webapp/images

/images/フォルダには次のファイルが含まれます。

スクリプト

/sample app/articles/src/main/webapp/scripts

/scripts/フォルダには、文字列とJSONオブジェクトとの変換に使用されるjson2.jsユーティリティ・スクリプトが含まれます。

スタイル

/sample app/articles/src/main/webapp/styles

/styles/フォルダには、このWebアプリケーションで使用されるCSSスタイルを指定するためのmain.cssが含まれます。

ビュー

/sample app/articles/src/main/WEB-INF/jsp

/jsp/フォルダには次のファイルが含まれます。

WEB-INF

/sample app/articles/src/main/WEB-INF

/WEB-INF/フォルダには次のファイルが含まれます。

72.3 RESTコールの実行

WebCenter Sites RESTリソースは、XMLおよびJSONという2種類の入出力フォーマットをサポートしています。目的の戻りフォーマットを取得するには、MIMEタイプapplication/xmlまたはapplication/jsonを指定するHTTPヘッダーを設定する必要があります。

たとえば、入力フォーマットをXMLに指定する場合は、Content-Typeapplication/xmlに設定します。出力フォーマットを指定する場合は、Accept (予期されるフォーマット)をapplication/xmlに設定します。その他の出力フォーマットを指定すると、それらは無視されます。Content-TypeまたはAcceptで何も指定されていない場合のデフォルトはXMLです(サンプル・コードについては、第72.3.1項「JavaScriptからのRESTコールの実行」の行64および66を参照)。

RESTコールの詳細は、この項の次のトピックを参照してください。

72.3.1 JavaScriptからのRESTコールの実行

次のコード(home.jsp)は、アセットのRESTサービスに対してAJAXコールを実行して、アセット・データを保存します。実際には、プロキシ・コントローラに対してリクエストが実行され、プロキシ・コントローラから宛先のRESTサービスにリクエストがリダイレクトされます。


注意:

JSONのstringifyライブラリ(http://json.org/js.html)を使用して、JavaScriptオブジェクトを文字列としてシリアライズします。文字列のかわりにJSONオブジェクトを記述する方が便利です。


  1. // Form the URL pointing to the asset service

  2. // to the proxy controller, which will redirect this request to the CS REST servlet.

  3. var idarr = assetId.split(":");

  4. var assetUrl = "${pageContext.request.contextPath}/REST/sites/${config.csSiteName}/types/" + idarr[0] + "/assets/" + idarr[1];

  5. // For the data object to be posted.

  6. var data =

  7. {

  8. "attribute" :

  9. [

  10. {

  11. "name" : "source",

  12. "data" :

  13. {

  14. "stringValue" : document.getElementById("source_e_" + assetId).value

  15. }

  16. },

  17. {

  18. "name" : "cat",

  19. "data" :

  20. {

  21. "stringValue" : document.getElementById("cat_e_" + assetId).value

  22. }

  23. }

  24. ],

  25. "name" : document.getElementById("name_e_" + assetId).value,

  26. "description" : document.getElementById("desc_e_" + assetId).value,

  27. // This should be removed.

  28. "publist" : "${config.csSiteName}"

  29. };

  30. // Convert JSON data to string.

  31. var strdata = JSON.stringify(data);

  32. // Perform AJAX request.

  33. var req = getXmlHttpObject();

  34. req.onreadystatechange = function ()

  35. {

  36. if (req.readyState == 4)

  37. {

  38. if (req.status == 200)

  39. {

  40. // On successful result

  41. // update the view controls with new values and switch the mode to 'view'.

  42. for (c in controls)

  43. {

  44. document.getElementById(controls[c] + "_v_" + assetId).innerHTML =

  45. document.getElementById(controls[c] + "_e_" + assetId).value;

  46. }

  47. switchMode(assetId, false);

  48. }

  49. else

  50. {

  51. // Error happened or the session timed out,

  52. // reload the current page to re-acquire the session.

  53. alert("Failed to call " + assetUrl + ", " + req.status + " " + req.statusText);

  54. window.location.reload( false );

  55. }

  56. }

  57. };

  58. // We put Content-Type and Accept headers

  59. // to tell CS REST API which format we are posting

  60. // and which one we are expecting to get.

  61. req.open("POST", assetUrl, true);

  62. req.setRequestHeader("Content-Type", "application/json;charset=utf-8");

  63. req.setRequestHeader("Content-Length", strdata.length);

  64. req.setRequestHeader("Accept", "application/json");

  65. req.send(strdata);

  66. }

72.3.2 JavaからのRESTコールの実行

次のコード(HomeController.java)はアセット検索サービスをコールして、FW_Articleタイプのすべてのアセットをリストします。このコードでは、Jersey Clientライブラリを使用して、WEMフレームワークが提供するrest-api-<version>.jarライブラリからオブジェクトを渡します。この方法を利用すると、Javaでの入力が強化されます。

SSOAssertion.get().createToken()メソッドをコールして、トークンをJavaコードから取得する必要がある点に注意してください。JavaScript側ではWEMのSSOに対してすでに認証が行われているため、同様の処理を行う必要はありません。

// Use Jersey client to query CS assets.
Client client = Client.create();
String url = config.getRestUrl() + "/types/FW_Article/search";
WebResource res = client.resource( url );
                
// Construct URL and add token (for authentication purposes)
// and fields (specify which fields to retrieve back) parameters.        
res = res.queryParam("fields", URLEncoder.encode("name,description,content,cat,source", "UTF-8"));
res = res.queryParam("ticket", SSO.getSSOSession().getTicket(res.getURI().toString(), config.getCsUsername(), config.getCsPassword()));
// Put Pragma: auth-redirect=false to avoid redirects to the CAS login page.
Builder bld = res.header("Pragma", "auth-redirect=false");
        
// Make a network call.
AssetsBean assets = bld.get(AssetsBean.class);

注意:

カスタム・ヘッダーPragma: auth-redirect=falseは、CAS SSOフィルタにCASサインイン・ページにリダイレクトしないように指示しますが、チケットが指定されていない場合または指定されたチケットが無効の場合は403エラーが返されます。


72.4 バイナリ・データを処理するURLの作成

「Articles」アプリケーションは、WebCenter SitesのBlobサーバーを使用してBLOBデータを処理します。次のユーティリティ関数は、特定のアセットの特定の属性のバイナリ・データを指すURLを作成する場合に使用できます。blobUrlには、Blobサーバー(デフォルトはhttp://localhost:8080/cs/BlobServer)を指定します。

public String getBlobUrl(String assetType, String assetId, String attrName, String contentType)
throws Exception
{
String contentTypeEnc = URLEncoder.encode(contentType, "UTF-8");
        
return blobUrl + "?" +
"blobkey=id" + 
"&blobnocache=true" +
"&blobcol=thumbnail" +
"&blobwhere=" + assetId +
"&blobtable=" + assetType +
"&blobheader=" + contentTypeEnc +
"&blobheadername1=content-type" +
"&blobheadervalue1=" + contentTypeEnc;
    }

バイナリ・データを取得する別の方法は、リソース/sites/{sitename}/types/{assettype}/assets/{id}を使用してアセットをロードすることです。ロードされたアセットには、BLOBサーバーを指すURLが格納されます。

72.5 コンテキスト・オブジェクト: WEMフレームワークからのパラメータへのアクセス

UIコンテナは、コンテナ内のすべてのアプリケーションにJavaScriptコンテキスト・オブジェクト(WemContext)を提供します。コンテキスト・オブジェクトは、アプリケーションでログイン済ユーザーやサイトに関する詳細情報をWEMフレームワークから取得するために使用します(通常は、UIコンテナから現在のサイトの名前を取得します)。また、コンテキスト・オブジェクトは、アプリケーションでデータを共有する際に使用する各種ユーティリティ・メソッドも提供します。コンテキスト・オブジェクトは、WebCenter Sitesと同一ドメインまたは異なるドメインで実行されているアプリケーションで使用できます。


注意:

wemcontext.htmlファイルには公開されるメソッドがリストされています(第72.5.3項「コンテキスト・オブジェクトで使用可能なメソッド」でまとめられています)。


この項の内容は、次のとおりです。

72.5.1 同一ドメイン用の実装

WebCenter Sitesドメイン内にあるアプリケーションのコンテキスト・オブジェクトを初期化して使用するには:

  1. wemcontext.jsを含めます(次のサンプル・コードの行1では、wemcontext.js<cs webapp path>/wemresources/js/WemContext.jsにあります)。

  2. WemContextオブジェクトのインスタンスを取得します(行3)。

  3. WemContextのメソッドを使用します(行4および5)。

例72-1 同一ドメイン用の実装のサンプル・コード

  1. <script src='http://<csinstalldomain>/<contextpath>/wemresources/js/WemContext.js'></script>

  2. <script type="text/javascript">

  3. var wemContext = WemContext.getInstance(); // Instantiate Context Object

  4. var siteName = wemContext.getSiteName(); // Get Site Name

  5. var userName = wemContext.getUserName(); // Get UserName

  6. </script>

72.5.2 クロスドメイン用の実装

クロスドメイン・アプリケーションのコンテキスト・オブジェクトを初期化して使用するには:

  1. wemxdm.jsjson2.jsおよびhash.htmlを(Misc/Samplesフォルダから)アプリケーションにコピーします。

  2. クロスドメイン・コールを実行するために、sample.htmlファイルを開いて、次のように変更します。

    1. wemxdm.jsjson.jsおよびhash.htmlのパスを、アプリケーション内でのそれぞれのパスに変更します(後述のコードの行1から4を参照)。

    2. wemcontext.htmlのパスを、WebCenter Sites内でのこのファイルの場所に変更します(wemcontext.html/wemresources/wemcontext.htmlにあります。WebCenter Sitesのホスト名とコンテキスト・パスを使用します。行14を参照してください。)

    3. インタフェース宣言で、フレームワークで使用するメソッドを指定します(行15)。

    4. このメソッドをローカル・スコープに実装し、リモート・メソッドを起動します(行30)。

例72-2 クロスドメイン・コール用のsample.html

  1. <script type="text/javascript" src="../js/wemxdm.js"></script>

  2. <script type="text/javascript">

  3. // Request the use of the JSON object

  4. WemXDM.ImportJSON("../js/json2.js");

  5. var remote;

  6. window.onload = function() {

  7. // When the window is finished loading start setting up the interface

  8. remote = WemXDM.Interface(/** The channel configuration */

  9. {

  10. // Register the url to hash.html.

  11. local: "../hash.html",

  12. // Register the url to the remote interface

  13. remote: "http://localhost:8080/cs/wemresources/wemcontext.html"

  14. }, /** The interface configuration */

  15. {

  16. remote: {

  17. getSiteName :{},

  18. ...

  19. }

  20. },/**The onReady handler*/ function(){

  21. // This function will be loaded as soon as the page is loaded

  22. populateAttributes();

  23. });

  24. }

  25. </script>

  26. <script type="text/javascript">

  27. /** Define local methods for accessing remote methods */

  28. function getSiteName(){

  29. remote.getSiteName(function(result){

  30. alert("result = " + result);

  31. });

  32. }

  33. ...

  34. </script>

72.5.3 コンテキスト・オブジェクトで使用可能なメソッド

表72-1 コンテキスト・オブジェクトで使用可能なメソッド

戻り型 メソッド名および説明

オブジェクト

getAttribute(attributename)

指定された属性名の属性値を返します。

オブジェクト

getAttributeNames()

すべての属性名を返します。

オブジェクト

getCookie(name)

指定された名前のCookie値を返します。通常のブラウザのCookieの制限がすべて適用されます。

オブジェクト

getCookies()

すべてのCookieを返します。

オブジェクト

getLocale()

ロケールを返します。

オブジェクト

getSiteId()

サイトIDを返します。

オブジェクト

getSiteName()

サイト名を返します。

オブジェクト

getUser()

ユーザー・オブジェクトを返します。

オブジェクト

getUserName()

ユーザー名を返します。

void

removeCookie(name, properties)

Cookieを削除します。

void

setAttribute(attributename, attributevalue)

属性を設定します。これらの属性には、他のアプリケーションからアクセスできます。

void

setCookie(name,value,expiredays,properties)

Cookieを設定します。


72.6 登録コード

第70.5項「認可モデル」で説明しているように、アプリケーションは登録することによってWEMフレームワークで公開されます。アプリケーションを登録すると、FW_Applicationタイプのアセットと、アプリケーションに関連付けられた各ビューに対してFW_Viewタイプのアセットが作成されます。アセット・タイプは、AdminSiteで有効になります。アセット・タイプの属性の定義は、Oracle Fusion Middleware WebCenter Sites REST API Beanリファレンスを参照してください。プログラムによる登録をお薦めします。手動登録の例は、第78章「WEMフレームワーク: アプリケーションの手動登録」を参照してください。

この項の内容は、次のとおりです。

72.6.1 iframeビューを使用したアプリケーションの登録

この項では、「Articles」サンプル・アプリケーションのコードを使用して登録プロセスについて説明します。「Articles」には、iframeタイプの単一ビューが含まれます。JavaScriptおよびHTMLのビューにも同じ手順が適用されます。

アプリケーションを登録するには:

  1. アプリケーションを表すアイコンを作成または取得します。(アイコンは、アプリケーション・バーに表示されます。)

    (「Articles」サンプル・アプリケーションは、次の場所にあるarticles.pngイメージ・ファイルを使用します。/sample app/articles/src/main/webapp/images/)

  2. アプリケーションのレイアウト(つまり各ビュー)をHTMLで指定するファイルを作成し、ビューでレンダリングされるコンテンツを保持するためのプレースホルダ・エレメントを作成します。図72-4に、アプリケーションとビューの関係を示します。

    たとえば、「Articles」サンプル・アプリケーションのlayout.jspには次の行が含まれます。

<div id="articles" style="float:left;height:100%;width:100%" class="wemholder"></div>

ビューのコンテンツは、アプリケーションが表示される際にプレースホルダ・エレメント内にレンダリングされます(layout.appがアプリケーションのレイアウトをレンダリングし、home.appがビューをレンダリングします)。


注意:

レイアウト・ファイルの作成時に、プレースホルダ・エレメントに一意のidを指定します。ビュー・オブジェクトをコーディングする際には、同じidparentnode属性に指定します。プレースホルダ・エレメントにclass="wemholder"を使用します。


図72-4 アプリケーションとビュー

図72-4の説明が続きます
「図72-4 アプリケーションとビュー」の説明

アプリケーションとビューは、多対多の関係にあります(図72-4)。1つのアプリケーションで複数のビューを使用でき、各ビューは複数のアプリケーションで使用できます。登録済のビューは(ビューのアセットIDによって)共有可能です。アセットIDが省略されている場合は、そのアプリケーションのコンテキスト内にビューが作成されます。ベーシックの場合、1つのアプリケーションに関連付けられるビューは1つのみです。

  1. PUT wem/applications/{applicationid} RESTサービスを起動して、アプリケーションBeanを指定します。Beanにビュー・アセットとアプリケーション・アセットに移入します。

    iframeビューの場合、「Articles」サンプル・アプリケーションのコード(InstallController.java)を使用します(コメント行// Create a new view objectおよび// Create a new application objectを見つけます)。layouturl属性を設定して、アプリケーションのレイアウト・ページのURLを指定します。

    「Articles」アプリケーションで、次のように、layouturl属性をlayout.app (LayoutController.javaで実装)のURLに指定します。

    app.setLayouturl(config.getArticlesUrl() + "/layout.app");
    

登録プロセスの結果をテストするには、WEM Adminインタフェースに一般管理者としてログインし、メニュー・バーで「アプリケーション」を選択します。このページにアプリケーションが一覧表示されるはずです。

72.6.2 JavaScriptビューおよびHTMLビューを使用したアプリケーションの登録

HTMLビューおよびJavaScriptビューを使用するアプリケーションの場合、前の項の手順に従いますが、次に示すサンプル・コードと属性を使用します。

72.6.2.1 JavaScriptビュー


注意:

ビューで指定したJavaScriptは、アプリケーションがレンダリングされるときにレンダリング(実行)されます。JavaScriptが他のビューと競合しないようにしてください。


サンプル・コード:

   window.onload = function () { 
      if (GBrowserIsCompatible()) { 
        var map = new GMap2(document.getElementById("map_canvas")); 
        map.setCenter(new GLatLng(37.4419, -122.1419), 13); 
        map.setUIToDefault(); 
      } 
   }
  • ソースURLからのJavaScriptビューのレンダリング

    次の属性を設定します。

    • name: ビューの名前

    • parentnode: (第72.6.1項「iframeビューを使用したアプリケーションの登録」の手順2からの)プレースホルダ・エレメントのID

    • viewtype: fw.wem.framework.ScriptRenderer。プレースホルダ・エレメントにJavaScriptをレンダリングします。

    • sourceurl: .jsファイルのパス。ビューのコンテンツを提供します。例: http://example.com:8080/js/drawTree.js

  • ソース・コードからのJavaScriptビューのレンダリング

    次の属性を設定します。

    • name: ビューの名前

    • parentnode: (第72.6.1項「iframeビューを使用したアプリケーションの登録」の手順2からの)プレースホルダ・エレメントのID

    • viewtype: fw.wem.framework.ScriptRenderer。プレースホルダ・エレメントにJavaScriptをレンダリングします。

    • javascriptcontent: JavaScriptコード(前述のサンプル。<script>タグはコードに含めないでください。)

72.6.2.2 HTMLビュー


注意:

ビューで指定したHTMLは、アプリケーションがレンダリングされるときにレンダリング(実行)されます。


サンプル・コード:

<object width="480" height="385">
 <param name="movie" value="http://www.localhost:8080/jspx/flash_slider_main.swf"></param>
 <param name="allowFullScreen" value="true"></param>
 <embed src=" http://www.localhost:8080/jspx/flash_slider_main.swf"
  type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true"
  width="480" height="385">
 </embed>
</object>
  • ソースURLからのHTMLビューのレンダリング

    次の属性を設定します。

    • name: ビューの名前

    • parentnode: (第72.6.1項「iframeビューを使用したアプリケーションの登録」の手順2からの)プレースホルダ・エレメントのID

    • viewtype: fw.wem.framework.IncludeRenderer。プレースホルダ・エレメントにJavaScriptをレンダリングします。

    • sourceurl: ビューのコンテンツを提供するHTMLファイルのパスです。例: http://example.com:8080/js/drawTree.jsp

  • ソース・コードからのHTMLビューのレンダリング

    次の属性を設定します。

    • view: ビューの名前

    • parentnode: (第72.6.1項「iframeビューを使用したアプリケーションの登録」の手順2からの)プレースホルダ・エレメントのID

    • viewtype: fw.wem.framework.IncludeRenderer。プレースホルダ・エレメントにJavaScriptをレンダリングします。

    • includecontent: HTMLコンテンツ(前述のサンプル。<html>または<body>タグはコードに含めないでください。)