JSFメモ

久々の技術ネタ。
Spring, JSF, Hibernateを使ったアプリケーション開発時の注意点をまとめてみる。とは云っても知識ゼロからスタートしているので、自分がつまづいたトコをメモっているだけですが。

では、JSFから。

・メッセージリソースの利用方法
これ小一時間程嵌りました。どのサイトを眺めてても、faces-config.xmlに「message-bundle」を追加すればOKと書いてあるものの、jspで実際にどうやって記述するのかが分からなかった。英語サイトとかまで手を伸ばして漸く解決。だけど合っているのだろうか?実際に書いたコードは以下のようなもの。

・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

・/jsp/index.jsp

<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.


・includeを使用する場合の注意点
次。includeの注意点。んー、これ厄介。心が折れそうになったw。
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!!

疲れたので今日はここまで。