<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <title>Pageクラス</title>
    <link rel="stylesheet" href="/css/style.css" type="text/css" media="all" />
    
    
  </head>
  <body>
    <div class="header">
      <div id="pane.left-header" class="pane left">
        <div id="org.seasar.kvasir.cms.toolbox.customPop-2" class="pop org.seasar.kvasir.cms.toolbox.customPop">
          <div class="body"><div class="wiki">
<ul>
<li><a href="/" class="pageNotFound">（サイトトップ）</a></li>
<li><a href="/download">ダウンロード</a></li>
<li><a href="/news/" class="pageNotFound">新着情報</a></li>
<li><a href="/docs/" class="pageNotFound">ドキュメント</a></li>
</ul>
</div>
</div>
        </div>
      </div>
      <div id="pane.right-header" class="pane right">
        <div id="org.seasar.kvasir.cms.toolbox.loginPop-1" class="pop org.seasar.kvasir.cms.toolbox.loginPop">
          <div class="body">
<form method="post" action="/plugins/toolbox/login.do/docs/1.0.x/ref/pageClass">
    <div class="row">
      <span class="label">Name</span>
      <span class="textinput"><input type="text" name="name" size="12" value="" /></span>
    </div>
    <div class="row">
      <span class="label">Password</span>
      <span class="textinput"><input type="password" name="password" size="12" value="" /></span>
    </div>
    <div class="row">
      <span class="submit"><input type="submit" value="Login" /></span>
    </div>
</form>
</div>
        </div><div id="org.seasar.kvasir.cms.pop.loginUserPop-1" class="pop org.seasar.kvasir.cms.pop.loginUserPop">
          <div class="body"></div>
        </div>
      </div>
    </div>
    <div class="page-frame">
      <div id="pane.left-sidebar" class="pane sidebar-frame sidebar subcontent">
        <div id="org.seasar.kvasir.cms.toolbox.searchPop-1" class="pop org.seasar.kvasir.cms.toolbox.searchPop">
          <h2 class="title">Search</h2>
          <div class="body"><form class="simple" method="get" action="/plugins/toolbox/search.do">
  <input type="text" name="query" size="12" />
  <input type="submit" value="Go!" />
</form>
</div>
        </div><div id="org.seasar.kvasir.cms.toolbox.customPop-1" class="pop org.seasar.kvasir.cms.toolbox.customPop">
          <h2 class="title">メニュー</h2>
          <div class="body"><ul>
  <li><a href="/" class="pageNotFound">（サイトトップ）</a></li>
  <li><a href="/download">ダウンロード</a></li>
  <li><a href="/news">新着情報</a></li>
  
    
    
      <li>
        <a href="/docs/1.0.x/user">ユーザマニュアル</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/user/description">Ymirとは</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/processFlow">Ymirの処理フロー</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/projectStatus">動作ステータス</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/generator">自動生成機能</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/vili">Eclipseプラグイン「Vili（ヴィリ）」</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/ve">Eclipseプラグイン「Ve（ヴェー）」</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/setUp">セットアップ</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/skeleton">空のアプリケーション</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/example">サンプルアプリケーションの作成</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/development">開発における注意点</a>
            
          </li><li>
            <a href="/docs/1.0.x/user/faq">FAQ</a>
            
          </li>
        </ul>
      </li><li>
        <a href="/docs/1.0.x/ref">リファレンスマニュアル</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/ref/pageClass">Pageクラス</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/pathMapping">リクエストパスとPageクラスのマッピング</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/response">レスポンス</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/fileupload">ファイルアップロード</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/typeConversion">型の自動変換</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/zptTemplate">ZPTテンプレート</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/constraintCheck">制約チェック</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/validation">バリデーション</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/transactionToken">トランザクショントークン</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/permissionCheck">権限チェック</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/objectScope">オブジェクトスコープ</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/i18n">国際化</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/exceptionHandler">例外処理</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/include">インクルード</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/conversation">カンバセーション</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/appProperties">アプリケーションの設定</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/dicon">diconファイルの扱い</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/standardArchitecture">アプリケーションアーキテクチャ標準</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/ymirJson">JSON連携</a>
            
          </li><li>
            <a href="/docs/1.0.x/ref/batch">バッチプログラムの作成</a>
            
          </li>
        </ul>
      </li><li>
        <a href="/docs/1.0.x/dev">Ymir開発者マニュアル</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/dev/build">Ymirのビルド</a>
            
          </li><li>
            <a href="/docs/1.0.x/dev/release">Ymirのリリース</a>
            
          </li><li>
            <a href="/docs/1.0.x/dev/update-ymir-fragment-dbflute">DBFluteフラグメントの更新</a>
            
          </li>
        </ul>
      </li><li>
        <a href="/docs/1.0.x/etc">その他</a>
        
      </li><li>
        <a href="/docs/1.0.x/glossary">用語集</a>
        <ul>
          <li>
            <a href="/docs/1.0.x/glossary/Vili">Vili</a>
            
          </li><li>
            <a href="/docs/1.0.x/glossary/ve">Ve</a>
            
          </li>
        </ul>
      </li>
    
  
  <li><a href="/roadmap">ロードマップ</a></li>
  <li><a href="https://www.seasar.org/issues/browse/YMIR">既知の不具合を閲覧する・不具合を報告する</a></li>
  <li><a href="https://www.seasar.org/svn/ymir/">SVNリポジトリ</a></li>
  <li><a href="http://svn.seasar.org/browse/?root=ymir">SVNリポジトリを閲覧</a></li>
</ul>
</div>
        </div>
      </div>
      <div id="pane.main" class="pane main">
      
        <div id="org.seasar.kvasir.cms.toolbox.breadcrumbsPop-1" class="pop org.seasar.kvasir.cms.toolbox.breadcrumbsPop">
          
          <div class="body"><ul>
  <li class="first"><a href="/">(TOP)</a></li><li><a href="/docs">ドキュメント</a></li><li><a href="/docs/1.0.x">ドキュメント（1.0.x系）</a></li><li><a href="/docs/1.0.x/ref">リファレンスマニュアル</a></li><li>Pageクラス</li>
</ul>
</div>
        </div><div id="org.seasar.kvasir.cms.pop.contentPop-1" class="pop org.seasar.kvasir.cms.pop.contentPop">
          <h2 class="title">Pageクラス</h2>
          <div class="body">
<ul class="information">
  
  <li>2009-03-13 14:49:20</li>
</ul>
<div class="content"><div class="document">
<p>Ymirではリクエストパスに対応するPageクラスのメソッドが呼び出されます。対応するPageクラスが存在しない場合、メソッド呼び出しは行なわれません。このクラスが存在する場合、以下のような処理が行なわれます。</p>
<ol>
<li>このクラスのインスタンスをS2Containerから取り出す（なおインスタンスはrequestスコープです）。<em>なお、Pageインスタンスについては、S2Containerによる暗黙的なDIは行なわれません。</em> S2ContainerによるDIを行ないたい場合は、@Bindingアノテーションを使って明示的に指定するか、Ymirの@Injectアノテーションを使用して下さい。</li>
<li>@Inアノテーションが付与されているsetterメソッドがあれば、アノテーションに従ったオブジェクトスコープからオブジェクトを取り出してそのsetterメソッドを使ってセットする。</li>
<li>@Populateアノテーションが付与されているGetter/Setterメソッドがあれば、アノテーションに従ったオブジェクトスコープからオブジェクトを取り出してそのGetter/Setterメソッドを使って値をセットする（リクエストパラメータはここでセットされます）。</li>
<li>Pageクラスに書かれている制約アノテーションに従って制約（リクエストパラメータの正当性やアクセス権限）のチェックを行なう。</li>
<li>Pageインスタンスについてアクションを実行する。具体的には、マッチしたパスマッピングから構築したアクション名と同じ名前のメソッドを呼び出す。アクション名と同じ名前のメソッドが存在しない場合は<tt class="docutils literal"><span class="pre">_default()</span></tt>メソッドを呼び出す。<tt class="docutils literal"><span class="pre">_default()</span></tt>メソッドも存在しない場合はActionNotFoundRuntimeExceptionをスローする。</li>
<li>メソッドの返り値からResponseオブジェクトを構築する。構築したResponseのtypeがPASSTHROUGHである場合、リクエストパスに対応するテンプレートファイルが存在しないかつマッチしたパスマッピングから構築したデフォルトの返り値がnullでない場合は、Responseオブジェクトをデフォルトの返り値から構築したResponseオブジェクトで置き換える。</li>
<li>ResponseのtypeがPASSTHROUGHの場合、Pageインスタンスの<tt class="docutils literal"><span class="pre">_prerender()</span></tt>メソッドを呼び出す。（このメソッドの中で、テンプレートのレンダリングに必要なオブジェクトやプロパティの準備を行なうようにして下さい。）</li>
<li>@Outアノテーションが付与されているGetterメソッドがあれば、アノテーションに従ったオブジェクトスコープにGetterメソッドの返り値を格納する。</li>
</ol>
<p>なお、制約チェックで失敗した場合はアクションメソッドの呼び出しの代わりに、<tt class="docutils literal"><span class="pre">_validationFailed</span></tt>メソッドまたは<tt class="docutils literal"><span class="pre">_permissionDenied</span></tt>メソッドが呼び出されます。具体的には、リクエストパラメータの正当性チェックに失敗した場合は<tt class="docutils literal"><span class="pre">_validationFailed</span></tt>メソッドが呼び出され、アクセス権限チェックに失敗した場合は<tt class="docutils literal"><span class="pre">_permissionDenied</span></tt>メソッドが呼び出されます。</p>
<p><tt class="docutils literal"><span class="pre">_validationFailed</span></tt>メソッドまたは<tt class="docutils literal"><span class="pre">_permissionDenied</span></tt>メソッドの呼び出しの後は、通常のアクションメソッドの場合と同じように返り値からResponseオブジェクトが構築されます。また<tt class="docutils literal"><span class="pre">_prerender()</span></tt>メソッドの呼び出し処理も通常と同じように行なわれます。</p>
<p><tt class="docutils literal"><span class="pre">_validationFailed</span></tt>メソッドが存在しない場合は単にメソッド呼び出しがスキップされますが、<tt class="docutils literal"><span class="pre">_permissionDenied</span></tt>メソッドが存在しない場合はPermissionDeniedExceptionがスローされます。<tt class="docutils literal"><span class="pre">_validationFailed</span></tt>メソッドが存在しない場合は<tt class="docutils literal"><span class="pre">_prerender()</span></tt>メソッドが呼び出されますが、<tt class="docutils literal"><span class="pre">_permissionDenied</span></tt>メソッドが存在せずにPermissionDeniedExceptionがスローされた場合は<tt class="docutils literal"><span class="pre">_prerender()</span></tt>メソッドの呼び出しは行なわれません。</p>
<div class="section" id="e382a2e382afe382b7e383a7e383b3e383a1e382bde38383e38389e381aee5bc95e695b0e580a4e381aee8a7a3e6b1ba">
<h3><a name="e382a2e382afe382b7e383a7e383b3e383a1e382bde38383e38389e381aee5bc95e695b0e580a4e381aee8a7a3e6b1ba">アクションメソッドの引数値の解決</a></h3>
<p>アクションメソッドが引数を持つ場合、引数に@org.seasar.ymir.scope.annotation.Resolveアノテーションを付与することでスコープからオブジェクトを取り出して引数の値とすることができます。これを「メソッド引数値の解決（resolution）」と呼びます。</p>
<p>引数にアノテーションが付与されていない場合はアクションメソッド毎に定義されているデフォルトの引数値が第1引数から順番に割り当てられます。それでも解決できない引数には引数の型に応じたデフォルト値が割り当てられます。</p>
<p>デフォルトの引数値は以下のように定義されています。</p>
<table border="1" class="docutils">
<colgroup>
<col width="32%" />
<col width="68%" />
</colgroup>
<thead valign="bottom">
<tr>
<th>アクションメソッド</th>
<th>デフォルトの引数値</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>（ボタンに対応しないアクション）</td>
<td>なし</td>
</tr>
<tr>
<td>（ボタンに対応するアクション）</td>
<td>ボタン名に<tt class="docutils literal"><span class="pre">name[param]</span></tt>のようにパラメータが付与されていればその値</td>
</tr>
<tr>
<td><tt class="docutils literal"><span class="pre">_prerender</span></tt></td>
<td>なし</td>
</tr>
<tr>
<td><tt class="docutils literal"><span class="pre">_validationFailed</span></tt></td>
<td>エラーメッセージ情報を持つNotesオブジェクト</td>
</tr>
<tr>
<td><tt class="docutils literal"><span class="pre">_permissionDenied</span></tt></td>
<td>スローされるためのPermissionDeniedExceptionオブジェクト</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="e4be8b">
<h3><a name="e4be8b">例</a></h3>
<p>標準のマッピングでは、例えばリクエストパスが/path.htmlである場合、アプリケーションのルートパッケージ名をcom.example.appとしてcom.example.app.web.PathPageクラスがPageクラスとなります。</p>
<p>今HTTPメソッドがPOSTであるようなリクエストが/path.htmlに対してなされた場合の処理の流れは以下のようになります。</p>
<div class="section" id="e588b6e7b484e38381e382a7e38383e382afe381a7e382a8e383a9e383bce381abe381aae38289e381aae38184e382b1e383bce382b9">
<h4><a name="e588b6e7b484e38381e382a7e38383e382afe381a7e382a8e383a9e383bce381abe381aae38289e381aae38184e382b1e383bce382b9">制約チェックでエラーにならないケース</a></h4>
<ol>
<li>PathPageインスタンスの取り出し</li>
<li>スコープ内オブジェクトのinject</li>
<li><tt class="docutils literal"><span class="pre">PathPage#_post()</span></tt>、なければ<tt class="docutils literal"><span class="pre">PathPage#_default()</span></tt>の呼び出し</li>
<li><tt class="docutils literal"><span class="pre">PathPage#_prerender()</span></tt>の呼び出し</li>
</ol>
</div>
<div class="section" id="e383aae382afe382a8e382b9e38388e38391e383a9e383a1e383bce382bfe381aee6ada3e5bd93e680a7e38381e382a7e38383e382afe381a7e382a8e383a9e383bce381abe381aae3828be382b1e383bce382b9">
<h4><a name="e383aae382afe382a8e382b9e38388e38391e383a9e383a1e383bce382bfe381aee6ada3e5bd93e680a7e38381e382a7e38383e382afe381a7e382a8e383a9e383bce381abe381aae3828be382b1e383bce382b9">リクエストパラメータの正当性チェックでエラーになるケース</a></h4>
<ol>
<li>PathPageインスタンスの取り出し</li>
<li>スコープ内オブジェクトのinject</li>
<li><tt class="docutils literal"><span class="pre">PathPage#_validationFailed()</span></tt>の呼び出し</li>
<li><tt class="docutils literal"><span class="pre">PathPage#_prerender()</span></tt>の呼び出し</li>
</ol>
</div>
<div class="section" id="e382a2e382afe382bbe382b9e6a8a9e99990e38381e382a7e38383e382afe381a7e382a8e383a9e383bce381abe381aae3828be382b1e383bce382b9">
<h4><a name="e382a2e382afe382bbe382b9e6a8a9e99990e38381e382a7e38383e382afe381a7e382a8e383a9e383bce381abe381aae3828be382b1e383bce382b9">アクセス権限チェックでエラーになるケース</a></h4>
<ol>
<li>PathPageインスタンスの取り出し</li>
<li>スコープ内オブジェクトのinject</li>
<li><tt class="docutils literal"><span class="pre">PathPage#_permissionDenied()</span></tt>の呼び出し、なければPermissionDeniedExceptionをスロー</li>
<li>（PermissionDeniedExceptionがスローされなかった場合）<tt class="docutils literal"><span class="pre">PathPage#_prerender()</span></tt>の呼び出し</li>
</ol>
</div>
</div>
<div class="section" id="e383aae382afe382a8e382b9e38388e38391e383a9e383a1e383bce382bfe381aee382a4e383b3e382b8e382a7e382afe38388">
<h3><a name="e383aae382afe382a8e382b9e38388e38391e383a9e383a1e383bce382bfe381aee382a4e383b3e382b8e382a7e382afe38388">リクエストパラメータのインジェクト</a></h3>
<p>リクエストパラメータはユーザが自由に外部から指定することができるため、リクエストパラメータをGetter/Setterメソッドを使って自動的にPageオブジェクトに設定できるようにしてしまうとアプリケーション設計者の意図しないGetter/Setterメソッドを使って外部からPageオブジェクトに値がセットされてしまう危険性があります。</p>
<p>この危険を回避するために、Ymirではリクエストパラメータスコープから値をインジェクトまたはポピュレートするようなアノテーションをGetter/Setterメソッドに明示的に付与するポリシーになっています。このアノテーションが付与されていないGetter/Setterはリクエストパラメータは代入されません。</p>
<p>ある名前のリクエストパラメータを代入したい場合は例えば以下のように記述して下さい:</p>
<pre class="literal-block">
@In(scopeClass = RequestParameterScope.class, name = &quot;parameter&quot;)
public void setParameter(String parameter) {
    this.parameter = parameter;
}
</pre>
<p>Setterに対応するプロパティ名と代入したいパラメータの名前が同じ場合はもう少し簡単に記述できます:</p>
<pre class="literal-block">
@In(RequestParameterScope.class)
public void setParameter(String parameter) {
    this.parameter = parameter;
}
</pre>
<p>さらにこれはエイリアスアノテーションを使って以下のように書けます:</p>
<pre class="literal-block">
@RequestParameter
public void setParameter(String parameter) {
    this.parameter = parameter;
}
</pre>
<p>ネストした形式のパラメータをオブジェクトグラフにマッピングするような形で代入したい場合は@Inアノテーションの代わりに@Populateアノテーションを使います。例えば<tt class="docutils literal"><span class="pre">user.name</span></tt>というパラメータの値をPage#getUser().setName()を使って代入したい場合は以下のように記述して下さい:</p>
<pre class="literal-block">
@Populate(RequestParameterScope.class)
public User getUser() {
    return user;
}
</pre>
<p>実は@RequestParameterは@Populate(RequestParameterScope.class)のエイリアスです。そのためSetterに@RequestParameterと@Inの両方のアノテーションが付与されている場合、@RequestParameterの評価順序は@Inよりも後になります。</p>
</div>
<div class="section" id="e38395e382a7e383bce382bae6af8ee381aee382abe382b9e382bfe383a0e383a1e382bde38383e38389e591bce381b3e587bae38197">
<h3><a name="e38395e382a7e383bce382bae6af8ee381aee382abe382b9e382bfe383a0e383a1e382bde38383e38389e591bce381b3e587bae38197">フェーズ毎のカスタムメソッド呼び出し</a></h3>
<p>Pageコンポーネントに関する処理フェーズ毎に特定のメソッドを呼ぶようにすることができます。</p>
<p>ある処理フェーズの時点で呼び出したいメソッドには<tt class="docutils literal"><span class="pre">org.seasar.ymir.annotation.Invoke</span></tt>アノテーションを付与します。アノテーションのプロパティとして、フェーズを表すEnum（<tt class="docutils literal"><span class="pre">org.seasar.ymir.Phase</span></tt>）を指定します。以下に例を示します:</p>
<pre class="literal-block">
@Invoke(Phase.PAGECOMPONENT_CREATED)
public void initialize() {
    ...
}
</pre>
<p>フェーズには以下のものがあります。</p>
<table border="1" class="docutils">
<colgroup>
<col width="33%" />
<col width="67%" />
</colgroup>
<thead valign="bottom">
<tr>
<th>フェーズ名</th>
<th>説明</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>PAGECOMPONENT_CREATED</td>
<td>Pageコンポーネントの生成直後（1.の直後）</td>
</tr>
<tr>
<td>OBJECT_INJECTED</td>
<td>オブジェクトのインジェクトの直後（2.の直後）</td>
</tr>
<tr>
<td>ACTION_INVOKING</td>
<td>アクションの実行前（6.の直前）</td>
</tr>
<tr>
<td>ACTION_INVOKED</td>
<td>アクションの実行後（6.の直後）</td>
</tr>
</tbody>
</table>
<p>Invokeアノテーションが付与されたメソッドが引数を持つ場合はアクションメソッドと同様に引数値の解決が行なわれます。デフォルトの引数値はありません。</p>
<p><em>[Ymir-1.0.2以降]</em> Invokeアノテーションが付与されたメソッドが返り値を返した場合、その返り値に従って画面遷移が行なわれます。</p>
</div>
</div>
</div>
</div>
        </div>
      
    </div>
    </div>
    <div class="footer-delimiter"></div>
    <div id="pane.footer" class="pane footer">
      <div id="org.seasar.kvasir.cms.pop.poweredByPop-1" class="pop org.seasar.kvasir.cms.pop.poweredByPop">
        <div class="body">Powered by Kvasir/Sora</div>
      </div>
    </div>
  </body>
</html>
