ゆっきーのブログ

実践的なシステム設計開発、アプリケーションフレームワーク開発、トラブルシューティング、 後輩育成のためのブログ。その他、キャンプ、トレッキング・登山やレジャー等。

1. システムエンジニアリング JavaEE7

JavaEE7のJSF, Facelets, JSPの関係

投稿日:2018年7月22日 更新日:


JavaEEを使ったアプリ開発の際に、いつも気になるが後回しにしていたこと…
HTML5への対応方法の調査等、今後の理解促進のために、調べてみた。


FaceletsとJSFとの関係は?

JSFはWebアプリ開発のためのフレームワークであり、ページレンダリングの機能として、JSPやFaceletsを使っている。JSF1.2までは標準でJSPが使用されていたが、JSF2.0からはレンダリング性能や利便性を向上するためにFaceletsが利用される。

用語 説明
JSP
(JavaServer Pages)
テンプレートからWebページを生成するための標準。
1999年に初版がリリースされており、既に古い標準になっている。
テンプレートの変更時やリロード時に、JSPコンパイラは、テンプレートからサーブレットのソースコードを生成する。このサーブレットをコンパイル・実行してページを生成する仕組み。
Facelets JSFのために開発されたWebページテンプレート技術。
XMLベースのテンプレート(xhtml)をSAXベースコンパイラで処理するため、JSPと比較して高速にページ生成ができる。
Apache Tapestryと近い実装になっている。
JSF
(JavaServer Faces)
JavaベースのWebアプリケーションフレームワークである。
JSF1.2からJava EEに採用されている。
JSF1.2まではJSPを使用してたが、それ以降はFaceletsを使用するよう変更された。
(実現技術としてJSPを使用していたので、JSPを置き換える仕様というわけではないようだ。)

JSF/JSP/JavaEEの対応は次の通り。

JSF JavaEE JSFが利用するエンジン 備考
JSF1.0/1.1 JSP JSF仕様の初回リリース、バグフィックスリリース
JSF1.2 JavaEE5 JSP/Facelets JSF1.2までJSPが標準。
設定変更でFaceletsも利用可。
JSF2.0 JavaEE6 Facelets JSF2.0からFaceletsが標準
JSF2.2 JavaEE7 Facelets HTML5対応

参考:
JSF 2.0 の新機能概要とFacelets テンプレートのご紹介 | 寺田 佳央 – Yoshio Terada


.jsp, .jsf, .xhtml等があるが、何を使うべきなのか?

JavaEE7(JSF2.0)以降を使用するのであれば.xhtmlを使用するべきである。
JSFを使用しない、後方互換等を考えるのであれば、.jsp/.jsfの使用も考慮する必要がある。

  • 拡張子: “.jsp”
    JSP用のファイル拡張子。
    この拡張子のファイルがリクエストされると、サーブレットコンテナに組み込まれているJspServletが当該ページをJSPとして処理する。
    web.xmlでのservlet-mappingによるリクエストパスとサーブレットとの対応付けは不要である。
  • 拡張子: “.jsf
    JSF1.2でよく使用されていた拡張子。
    JSF1.2を使用する際、次のようなweb.xmlの宣言が行われていた。

    <servlet-mapping>
        <servlet-name>facesServlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    

    “*.jsf”という仮想パスが要求された場合、FacesServletがサーブレットで処理を行う、という設定である。FacesServletはFaceletsの機能を実装したサーブレットであり、要求された仮想パスに対応する”.xhtml”ファイル(物理ファイル)を解析して、実際のページを生成して返却する。
    ユーザに見せるパスはあくまでも.jsfであり、セキュリティ上の理由で内部処理用の.xhtmlはユーザに見せない、という考えである。(この設定が行われない場合、ユーザがxhtmlファイルの中身を見ることができてしまう。)

    なお、JSF1.0/1.1との互換性を維持するために、”*.faces”や”/faces/*”がマッピングされる場合もある。

    <servlet-mapping>
        <servlet-name> faces-servlet-name </servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
        <servlet-name> faces-servlet-name </servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>
    

    参考だが、FacesServletが使用する物理ファイルは次のように変更可能である。(下記は.xhtmlではなく.xmlを使用する場合の例)

    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xml</param-value>
    </context-param>
    
  • 拡張子: “*.xhtml”
    JSF2.0以降では*.xhtmlがFacesServletにマッピングされることになった。
    ページを作る際もアクセスする際もどちらも.xhtmlを使用する。
    (JSF1.2の時のように*.xhtmlをユーザに隠す必要はなくなった。)
    JSF1.2では次のように.xhtmlをFacesServletにマッピングする設定を行うと無限ループになってしまうが、JSF2.0以降では正しく動作する。

    <servlet-mapping>
        <servlet-name>facesServlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    

参考:
What is the difference between creating JSF pages with .jsp or .xhtml or .jsf extension – Stack Overflow
web.xml – Sometimes I see JSF URL is .jsf, sometimes *.xhtml and sometimes /faces/. Why? – Stack Overflow


JSF2.2のHTML5のサポートとは?

HTML5ではカスタムの要素や属性の定義が可能となった。
このようなHTML5の仕様に対応するために、JSF2.2では次の機能が追加された。

  • パススルー要素:
    HTML5の要素や属性をJSFコンポーネントと同様にサーバサイドのインスタンスに対応付けできる。次の例では、”jsf:”という名前空間を宣言し、input要素で”jsf:id=…”と使用している。結果として、この要素はサーバサイドでFacelets要素として扱われる。

    <html ... xmlns:jsf="http://xmlns.jcp.org/jsf"
    ...
        <input type="email" jsf:id="email" name="email"
               value="#{reservationBean.email}" required="required"/>
    
  • パススルー属性:
    パススルー要素とは逆に、JSFコンポーネントで指定する属性をJSFコンポーネントの属性として処理しないように指定できる。
    次の例では、”p:”という名前空間を宣言し、JSFの属性として処理せずにそのままレンダリングする属性に対して、”p:type=..”, “p:min=…”等のように属性を指定している。
    なお、JSF2.1以前では、JSFコンポーネントに存在しない属性を指定した場合、レンダリングされない。名前空間”p:”はPrimeFacesで使用されることがあるため、混乱を避けるために”pt:”という名前空間を使う場合もある。

    <html ... xmlns:p="http://xmlns.jcp.org/jsf/passthrough"
    ...
        
    <h:form prependId="false">
    <h:inputText id="nights" p:type="number" value="#{bean.nights}" 
                 p:min="1" p:max="30" p:required="required" 
                 p:title="Enter a number between 1 and 30 inclusive.">
            ...
    

結果として開発者は、次のようにページ作成の方法を選択できる。
個人的には、これまでJavaEE6での実装を行っていたので、1.の方法に馴染んでいるが、HTML5の対応を進めるのであれば、2.の方法にも慣れていく必要がある。

  1. , 等のJSFコンポーネントを使った従来からのページ作成方法
  2. 上記のJSFコンポーネントのタグは使用せずに、HTML5を使ってページを作成する方法。HTML5の要素にて、JSFと対応付けをマークするための”jsf:id”等の属性を使用する。
  3. 上記の2つをミックスしたページ作成方法

参考:
8.9 HTML5-Friendly Markup – Java Platform, Enterprise Edition: The Java EE Tutorial (Release 7)
Custom HTML tag attributes are not rendered by JSF – Stack Overflow
HTML5とJSF, //enterprise java /


HTML5なのにxhtmlを使用するのか?

ブラウザはページ上のdoctypeでHTMLの種類は識別するので、ファイルの拡張子は重要ではない。
また、HTML5はXHTMLの要件を満たしているため、XHTMLファイル上にHTML5の記述をしても仕様上・実装上の問題はなく、既存のFacesServletを利用できる。

  • ブラウザはページの拡張子ではなく、doctypeに宣言された値に基づいて、対象ページがHTML5/HTML4.01/XHTML1.0等かを識別する。
  • faceletsは、特定のdoctypeの宣言を強制しない。faceletsとしては、どんなdoctypeが宣言されても関知しない。
  • JSF2.2ではHTML5をサポートするが、上記の通りパススルー要素/属性がメインの対応であり、やはりdoctypeについては関知しない。
  • XHTMLは、コンピュータで各種処理で処理しやすいよう、開始/終了タグの関係を厳密に定義すること期待する仕様になっている。HTML5では、人やコンピュータが処理しやすいよう、この要件を満たしているので、XHTMLでHTML5のタグを表現することは可能である。
    (厳密には、HTML5とXHTML1.0で異なる箇所もあるので完全な互換があるわけではない。)

参考:
jsf – JavaServer Faces 2.2 and HTML5 support, why is XHTML still being used – Stack Overflow

番外

  • Mojjara: SunのJSFのリファレンス実装(JSF RI)。はGlassfishプロジェクトの一環で開発が進められた。1.2_08以降では、Glassfish以外でも利用できるようにしたのがMojjara。
  • 要素とタグ: 「タグ」とは、要素の開始/終了を示す識別子である。「要素」とは、開始から終了タグまで定義されるコンテンツを意味する。

-1. システムエンジニアリング, JavaEE7
-, , , ,

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Wildfly11のインストール

このサイトでWebアプリを公開したい。 仕事ではJBoss Enterprise Application Server(JBoss EAP)を使う機会が多いのでそれを使いたいがライセンス料がかかる。無 …

疎通確認用pingツール

新人君たちと本番環境の構築作業でデータセンターに入り。 構築したサーバから、既存の重要なサーバへの疎通確認を行うために、pingを何度も入力する予定とのこと。 作業時間の短縮や間違いの低減のために、こ …

EAP7のインストールとパッチ適用

仕事でredhat社のEnterprise Application Server7(EAP7)を扱うことが多いので備忘録として記載します。 なお、このサイトでWebアプリを公開したいと考えていますが、 …

CentOS7のマルチホーム化

サイトの存在を隠しつつも、sftpサーバを公開し、後輩と1G以上のファイルのやりとりしたい。 パブリック側のIPアドレスを教えてしまうと、どこのサーバだろうかとブラウザで開いたりするとサイトの存在がわ …

テキストファイルマスクツール

本番環境での性能検証でNGになってしまった。 どの処理でどれほどの処理時間がかかっているかを把握するためにログレベルを変更して、ログを取得した。 対応方法を自社の担当者と検討するために、本番環境からこ …