読者です 読者をやめる 読者になる 読者になる

ひこぽんのーと

覚書と雑記です。

JavaEE 7をやってみよう。 JSF テンプレートXML その1

JavaEE JPA編から一時、横道にそれる。

JPAを使って登録、削除をやろうとした時、
どうしても入力が必要なので、
登録・削除用のVIEWを作ろうと思う。

どうせなら、JSFのテンプレート機能をを使おうと思って、
ちょっと調べてみた。

このへんの記事を読んで、わかったこと。

  • XMLネームスペースに"http://java.sun.com/jsf/facelets"を追加することで、
    テンプレート用(ってかFacelet用だけど)のタグが使える。
  • faceletsカスタムタグのinsertタグをテンプレートに定義しておくと、
    実態のVIEWからはめ込むhtmlを指定できる。

これだけで、一応テンプレートが作れそうなので、やってみた。
VIEWの形状をヘッダ、サイドメニュー、本文、フッタを持つ、よくある形式にしてみた。

構成

コンテンツは画面パーツ、レイアウトがひな形、
ビューがレイアウトに従い、パーツを組み合わせた画面と捉えるとわかりやすい。

WebContent
 + jsf
   + contents
   | + common
   | |  footer.xhtml
   | |  header.xhtml
   | |  htmlHeader.xhtml
   | |  menu.xhtml
   | |
   | + warship
   |   contents.xhtml
   |
   + layout
   | + common
   |   layout.xhtml
   |
   + view
      warship.xhtml
jsf/layout/common/layout.xml

画面の基礎となるレイアウト。
定義は単純で、画面構成のヘッダ、サイドメニュー、本文、フッタを定義している。
内、ヘッダ、サイドメニュー、フッタはincludeタグを使用してレイアウトで読み込むように定義して、
このレイアウトを使う限り、必ず付加されるようになっている。
加えて、metaタグなんかを含む共通のhead要素であるhtmlHeader.xhtmlも組み込んでいる。
唯一、本文だけはinsertタグを使ってレイアウトを使用するviewからhtmlを指定できる形になっている。

<!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"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
<ui:include src="/jsf/contents/common/htmlHeader.xhtml"/>
<ui:insert name="extHeader" />
<body>
    <div id="wrapper">
        <div id="header">
            <div id="header_body">
                <ui:include src="/jsf/contents/common/header.xhtml"/>
            </div>
        </div>
        <div id="contents">
            <ui:insert name="content" />
        </div>
        <div id="left-sidebar">
            <ui:include src="/jsf/contents/common/menu.xhtml"/>
        </div>
        <div id="footer">
            <ui:include src="/jsf/contents/common/footer.xhtml"/>
        </div>
    </div>
</body>
</html>
jsf/contens/common/header.xhtml, htmlHeader.xhtml, footer.xhmtl, menu.xhtml

4ファイルともほぼスタブなのだが、特筆する箇所といえば、
htmlHeader.xhtmlに定義したHTMLタイトル。
タイトルタグを指定すると、ブラウザのタイトルバーにページタイトルが表示されるが、
あれを動的に設定できるようにしている。
動的に変えるコンテンツにはinsertタグを用いるのはこれまで通りだが、
タグの中にデフォルト文字列を書いておくことで、
設定時/未設定時の値を使い分けることができるってことらしい。

<!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"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
  <h:head>
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Cache-Control" content="no-cache" />
    <title><ui:insert name="title">Default title</ui:insert></title>
    <h:outputStylesheet library="css" name="default.css" />
  </h:head>
</html>

[残り3ファイルはこちら](クリックで開く)

<!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"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
<h:body>
    <h:outputLabel value="#{staticText['site-title']}" />
</h:body>
</html>
<!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"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
<h:body>
    <h:outputLabel value="#{staticText['copyright']}" />
</h:body>
</html>
<!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"
      xmlns:h="http://java.sun.com/jsf/html">
<h:body>
    <div>艦艇図鑑</div>
    <div>艦艇登録</div>
    <div>艦艇編集</div>
    <div>艦艇削除</div>
</h:body>
</html>

jsf/contents/warship/warship.xhtml

艦艇一覧を表示する画面パーツという位置付けのファイル。
以前、JSFの回に書いたテーブルタグによるリスト形式のhtmlと同じような内容となっている。
なんか、無駄にxmlnsをインクルードしているのはご愛嬌ってことで。。。
JPAの流れではJSF用のManaged Beanを作っていなけれど、
これに合わせて、後ほどManaged Beanを作ることになる。

<!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"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:fn="http://java.sun.com/jsp/jstl/functions"
      xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
      xmlns:x="http://java.sun.com/jsp/jstl/xml">
<h:body>      
    <h:form id="form1">
        <h2><h:outputLabel value="艦艇図鑑" /></h2>
        <h:dataTable var="item" value="#{warShipCat.allList}" styleClass="table" headerClass="headerrow" rowClasses="oddrow,evenrow">
            <h:column>
                <f:facet name="header">No.</f:facet>
                <h:outputText value="#{warShipCat.allList.rowIndex + 1}" />
            </h:column>
            <h:column>
                <f:facet name="header">艦種</f:facet>
                <h:outputText value="#{item.warshipType.name}" />
            </h:column>
            <h:column>
                <f:facet name="header">名前</f:facet>
                <h:outputText value="#{item.name}" />
            </h:column>
        </h:dataTable>
    </h:form>
</h:body>
</html>
jsf/view/warship.xhtml

実際に呼び出す画面となるhtml。
注目すべきはcompositionタグ。
これを使うことでレイアウトを合成できる。
compositionタグの中にxmlnsの定義を書いているのが奇妙といえば奇妙だけれど、
そういうものなんだろうと、いうことにした。
テンプレート側でinsertタグを用いた箇所に値を設定するには、defineタグを用いる。
ここでは、HTMLタイトルと本文をdefineタグを使って値を設定している。

<!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">

  <ui:composition xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      template="/jsf/layout/common/layout.xhtml">
      
    <ui:define name="title">艦艇図鑑</ui:define>
    
    <ui:define name="content"> 
      <ui:include src="/jsf/contents/warship/content.xhtml"/>           
    </ui:define>
    
  </ui:composition>
</html>

と、JSFのVIEWについてはこれまで。
あと、header.xhtmlやfooter.xhtmlに固定文字列を設定するためのリソースファイルや、
画面デザインのためのCSSを作成した。
これらをすべてWebプロジェクトに組み込めばViewの完成。
あとはManaged Beanを作るだけ。

といったところで、次回へ続く。

注) 生成したHTMLについては、JSF テンプレートXML その3にも言及があるので、
そちらも参照のこと。

[残りファイルはこちら](クリックで開く)

  • statictext.properties
site-title= 艦艇これくしょん
copyright=(C) ひこぽん(nagamitsu1976)
@CHARSET "UTF-8";
#wrapper {
  text-align: left;
  width: 804px;
  margin: 0 auto;
  padding: 0;
  border: 2px solid black;
}

#header {
  height: 100px;
  margin: 0;
  padding: 0;
  border-color: black;
  border-width: 0px 0px 2px 0px;
  border-style: solid;
  background-color: #e6e6fa;
}

#header_body {
  text-align: center;
  position: relative; 
  top: 40%; 
  right: 0; 
  bottom: 0; 
  left: 0;  
}

#contents {  
  width: 580px;
  float: right;
  margin: 0;
  padding: 10px 10px 10px 10px;
  border-color: black;
  border-width: 0px 0px 0px 2px;
  border-style: solid;
}

#left-sidebar {
  height: 100%;
  width: 180px;
  float: left;
  margin: 0;
  padding: 10px 10px 10px 10px;
  border: 0px solid black;
}

#footer {
  text-align: center;
  clear: both;
  margin: 0;
  padding: 0.5em 0;
  border-color: black;
  border-width: 2px 0px 0px 0px;
  border-style: solid;
  background-color: #e6e6fa;
}

.headerrow {
	background-color:#e6e6fa;
}
.oddrow {
    background-color:#ffffff;
}
.evenrow {
	background-color:#ffffcc;
}
.table {
	width: 300px;
	background-color: #b0c4de;
	border: 1px solid #boc4de;
}
  • faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
    version="2.2">
    <application>
        <locale-config>
            <default-locale>ja</default-locale>
        </locale-config>
        <resource-bundle>
            <base-name>resources.statictext</base-name>
            <var>staticText</var>
        </resource-bundle>
    </application>

</faces-config>