JSFメモ
久々の技術ネタ。
Spring, JSF, Hibernateを使ったアプリケーション開発時の注意点をまとめてみる。とは云っても知識ゼロからスタートしているので、自分がつまづいたトコをメモっているだけですが。
では、JSFから。
・faces-config.xml
<application> <message-bundle>mypackage.resources.ApplicationResources</message-bundle> <locale-config> <default-locale>ja</default-locale> </locale-config> </application>
・/WEB-INF/classes/mypackage/resources/ApplicationResources.properties
・/WEB-INF/classes/mypackage/resources/ApplicationResources_ja.properties
def_keyword=Sample Keyword def_description=JSF Sample Application def_css=/css/default.css
<f:loadBundle basename="mypackage.resources.ApplicationResources" var="msg"/> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <meta name="keywords" content="<h:outputText value='#{msg.def_keyword}'/>"> <meta name="description" content="<h:outputText value='#{msg.def_description}'/>"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>JSF Amazon Sample Application</title> <link rel="stylesheet" type="text/css" href="<h:outputText value='#{msg.def_css}'/>"> ** 以下省略 **
faces-config.xmlに羅列したlocaleの分だけpropertiesファイルを用意する必要がある。デフォルトエンコードの場合「_ja.properties」などの地域名は必要ないのだが、今回は一応それも用意しておいた。
一方で、jsp側でメッセージリソースを利用する場合、「f:loadBundle」でリソースを読み込む必要があるらしい。faces-config.xmlに記述してるんだから二度手間のような気がするのは俺だけか?
「h:outputText」「f:loadBundel」など、JSFのタグを利用する場合、必ず「f:view」タグで囲んである必要がある。これってJSFの常識なんでしょうが、気づかずに結構悩みました。
画面的にはエラーは出ないんだけど、全く表示が行われません。tomcatの方のログを見ると以下のようなエラーが出ていたので、こんなエラーの場合は「f:view」を疑いましょう。
ERROR [http-8080-Processor24] UIComponentTagUtils.setValueProperty(172) | Component javax.faces.component.UIViewRoot is no ValueHolder, cannot set value.
jsp内でいつも通り、下記のように記述していたら、表示される順番(表示順)がバラバラだった。いや、バラバラというか、JSFのカスタムタグの記述が先行して表示されてしまっていた。
・header.jsp
<%@ page contentType="text/html;charset=Shift_JIS" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <f:view> <f:loadBundle basename="mypackage.resources.ApplicationResources" var="msg"/> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <meta name="keywords" content="<h:outputText value='#{msg.def_keyword}'/>"> <meta name="description" content="<h:outputText value='#{msg.def_description}'/>"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>JSF Sample Application</title> <link rel="stylesheet" type="text/css" href="<h:outputText value='#{msg.def_css}'/>"> </head> </f:view> <body> <div id="header"> JSF Sample Application </div>
・index.jsp
<%@ page contentType="text/html;charset=Shift_JIS" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ include file="parts/header.jsp" %> <f:view> <%-- body start --%> <h:outputText value="ただいまJSFサンプルサイトを構築中です。"/> <div id="books"> <h:outputText value="#{Books.headTitle}" /> </div> <%-- body end --%> </f:view> <%@ include file="parts/footer.jsp" %>
表示結果を見ると、index.jsp内のカスタムタグ内容が先に出力され、その後<div id="books">が出力されていた。
結論から云うと、「inculdeタグ」も「f:view」の中に記述しておかないと表示順がおかしくなってしまうらしい。(※このあたりは、コンパイルされたjavaファイルをきちんと見ていないのでなんともいえないが)
んで、「includeタグ」も「f:view」の中に含まれるようにコードを修正。
すると、こんどは以下のようなエラー!
Caused by: javax.servlet.ServletException: javax.servlet.jsp.JspException: Illegal to flush within a custom tag
カスタムタグの中で不正にフラッシュされちゃってるよってか。少し悩んでincludeされた方(この場合は、header.jsp)の「f:view」タグを取っ払ってやったら、正しく表示されました。いやー、長かった。たかがこんだけやるのに4時間近く費やしてしましました。まだまだ勉強する事が多いぞJSF!!
疲れたので今日はここまで。