JavaEE 6 をテキストエディタだけで(4) - JSF編

前回の続きでJSFの導入
blog1.mammb.com

web.xml の作成

ここまで設定ファイルレスでやってきたが、現在 JSF は Servlet3.0 の web.xml レスには対応していない。ここで作成する
src/main/webapp/WEB-INF/web.xml を作成

<?xml version='1.0' encoding='UTF-8'?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>
</web-app>
  • サーブレットとして FacesServlet を登録
  • URLパターンはなんでも良いが、*.faces にしておく

JSF の API 依存追加

POMに以下の依存を定義

<dependency>
    <groupId>javax.faces</groupId>
    <artifactId>jsf-api</artifactId>
    <version>2.1</version>
    <scope>provided</scope>
</dependency>


全体としては以下

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>etc9</groupId>
    <artifactId>webapp001</artifactId>
    <version>0.1</version>
    <packaging>war</packaging>

    <name>webapp001</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.ejb</artifactId>
            <version>3.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>javax.persistence</artifactId>
            <version>2.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

ManagedBean の作成

JSF ManagedBean を作成する。今回は src/main/java/etc9/web/BookController.java として作成。

package etc9.web;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;

import etc9.domain.Book;
import etc9.service.BookService;

@ManagedBean
public class BookController {
    
    @EJB 
    private BookService bookService;
    
    private Book book = new Book();
    private List<Book> bookList = new ArrayList<>();
    
    @PostConstruct
    public void doPostConstruct() {
        bookList = bookService.findAll();
    }
    
    public String listBooksAction() {
        bookList = bookService.findAll();
        return "listBooks.xhtml";
    }

    public String registerBookAction() {
        book = bookService.create(book);
        return "registeredBook.xhtml";
    }

    public Book getBook() { return book; }
    public void setBook(Book book) { this.book = book; }

    public List<Book> getBookList() { return bookList; }
    public void setBookList(List<Book> bookList) { this.bookList = bookList; }
}
  • @ManagedBean アノテーションにより JSP管理ビーンをコンテナに通知
  • book と bookList はいわゆるバッキングビーンで、クライアントからのリクエスト内容がコンテナによりgetter/setterを通して自動的に設定される
  • listBooksAction() と registerBookAction() はクライアントからの(ボタン押下などの)アクションに応答するメソッド

一覧ページの作成

JSF では(主に)xhtml ファイルをテンプレートとしてレスポンスを生成する。JSP のように Javaクラスへのコンパイルは行われない。
DBから取得した一覧(BookControllerのbookList)を表示する src/main/webapp/listBooks.xhtml ページを作成

<!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" xmlns:f="http://java.sun.com/jsf/core">
<h:head><title>List of the books</title></h:head>
<h:body>
    <h1>List of the books</h1>
    <h:dataTable value="#{bookController.bookList}" var="book" border="1">
        <h:column>
            <f:facet name="header"><h:outputText value="ID"/></f:facet>
            <h:outputText value="#{book.id}"/>
        </h:column>
        <h:column>
            <f:facet name="header"><h:outputText value="TITLE"/></f:facet>
            <h:outputText value="#{book.title}"/>
        </h:column>
        <h:column>
            <f:facet name="header"><h:outputText value="DESCRIPTION"/></f:facet>
            <h:outputText value="#{book.description}"/>
        </h:column>
    </h:dataTable>
    <hr/>
    <h:form>
        <h:link value="Create a new book" outcome="registerBook.xhtml"/>
    </h:form>
    
</h:body>
</html>
  • #{} で EL式にて ManagedBean として登録した BookController のプロパティを指定

登録フォームの作成

登録用に src/main/webapp/registerBook.xhtml を作成

<!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:head>
    <title>Register a new book</title>
</h:head>
<h:body>
    <h1>Register a new book</h1>
    <h:form>
        <h:panelGrid columns="2" >
            <h:outputLabel value="Title :"/>
            <h:inputText value="#{bookController.book.title}"/>

            <h:outputLabel value="Description  : "/>
            <h:inputTextarea value="#{bookController.book.description}" cols="20" rows="5"/>
        </h:panelGrid>
        <h:commandButton value="Register" action="#{bookController.registerBookAction}"/>

    </h:form>
</h:body>
</html>
  • h:commandButton タグにて 登録ボタン押下時のアクション #{bookController.registerBookAction} を指定

登録完了ページの作成

src/main/webapp/registeredBook.xhtml

<!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:head>
    <title>Registered</title>
</h:head>
<h:body>
    <h1>Registered!!</h1>
    <h:form>
        <h:commandLink value="Go to List" action="#{bookController.listBooksAction}"/>
    </h:form>
</h:body>
</html>

デプロイと実行

は前回までと同じ。登録画面

登録完了

登録内容を一覧に表示


バリデーション

簡単なバリデーションは xhtml ファイルに記載することあができる

<!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"
                                           xmlns:f="http://java.sun.com/jsf/core">
<h:head>
    <title>Register a new book</title>
</h:head>
<h:body>
    <h1>Register a new book</h1>
    <h:form>
        <h:panelGrid columns="3">
        
            <h:outputLabel value="Title :"/>
            <h:inputText id="title" value="#{bookController.book.title}" 
                    label="Title" required="true">
            </h:inputText>
            <h:message for="title" style="color:red"/>
            
            <h:outputLabel value="Description  : "/>
            <h:inputTextarea id="description" value="#{bookController.book.description}" 
                    label="Description" cols="20" rows="5">
                <f:validateLength maximum="10"/>
            </h:inputTextarea>
            <h:message for="description" style="color:red"/>
            
        </h:panelGrid>
        <h:commandButton value="Register" action="#{bookController.registerBookAction}"/>

    </h:form>
</h:body>
</html>



日本語にローカライズされたメッセージは、デフォルトだと難あり・


次回は CDI

blog1.mammb.com