Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > JSF 2.0 UI Component


Автор: AndrewMormysh 25.8.2009, 01:28
Поделитесь пожалуйста опытом создания кастомных компонентов на JSF 2.0.
Как известно jsf 2.0 rc вышел неделю назад - брожу по бескрайним просторам, но никак не могу найти хорошей статьи или какой-то документации по этому поводу. Есть буквально несколько бедных статеек без ссылок на источники: http://weblogs.java.net/blog/driscoll/archive/2008/11/jsf_20_writing_1.html, http://tapestryjava.blogspot.com/2008/11/simple-jsf-20-component-vs-tapestry.html. Да и то материал годичной давности (не понимаю правда как такое могло получиться) ((

В общем, есть ли кто нибудь с опытом в этой области? smile 

Автор: powerOn 25.8.2009, 07:24
Цитата(AndrewMormysh @  25.8.2009,  02:28 Найти цитируемый пост)
В общем, есть ли кто нибудь с опытом в этой области? 


Опыт есть небольшой smile. Могу выложить пример простого JSF 2.0 компонента если желаете. А по поводу документации, так это нужно http://jcp.org/en/jsr/detail?id=314смотреть.

Автор: AndrewMormysh 25.8.2009, 11:36
Цитата(powerOn @  25.8.2009,  06:24 Найти цитируемый пост)
Могу выложить пример простого JSF 2.0 компонента если желаете

Желаем  smile еще как желаем
На код не скупись, и компонент и пример использования.. и дескрипторы все )) ну в общем чем больше информации тем лучше, а то как-то ее совсем мало везде (

За линк спасибо, буду читать. Это единственное на данный момент место где можно черпать знания по этой теме?

Автор: powerOn 25.8.2009, 12:18
Цитата(AndrewMormysh @  25.8.2009,  12:36 Найти цитируемый пост)
Это единственное на данный момент место где можно черпать знания по этой теме? 


Я большего пока не находил. Есть еще https://javaserverfaces.dev.java.net/, но там дока та же что и в JSR + несколько статеек. Пример постараюсь вечером накатать и выложить, ибо сейчас на работе времени свободного немного.

Автор: powerOn 25.8.2009, 22:26
В общем накатал небольшой пример компонента для простого отчета в виде таблицы. Мавен-проект со всеми исходниками прикреплен, его можно скачать и собрать из консоли или IDE командой:
Цитата
mvn clean install


Сейчас я опишу основные шаги по конфигурации JSF 2.0 проекта, но рассчитываю на то Вы уже знакомы с JSF как таковым, например писали что нибудь на JSF 1.2 и Facelet-ах, и, конечно же, понимаете что такое Maven и как с ним работать.

Ну, поехали:
1) Создайте мавен проект с типом упаковки war. В pom файл необходимо добавить следующие зависимости:
Код

    <dependencies>
       <!-- JSF 2.0 -->
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>


Тут у нас последние снапшоты JSF 2.0 библиотек, а так же JSTL, которая им необходима. Наити эти зависимости можно в следующем репозитории:
Код

    <repositories>
        <repository>
            <id>download.java.net</id>
            <url>http://download.java.net/maven/2</url>
            <snapshots>
                <updatePolicy>daily</updatePolicy>
            </snapshots>
        </repository>
    </repositories>


2) Сконфигурируйте web.xml. Так же как и для JSF 1.2 для второй версии понадобится объявить Faces Servlet и ряд не совсем обязательных, но иногда полезных свойств:
Код

<?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">
    <display-name>myjsfcomp</display-name>
    
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>false</param-value>
    </context-param>

    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
        <param-value>true</param-value>
    </context-param>

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

    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>


3) Наш будущий компонент будет описан исключительно разметкой. Он будет отображать табличку с данными (что-то вроде отчета). Использоваться на странице он будет как обыкновенный тег, который связан через атрибут с данными для отчета.  Для создания такого компонента нужно в папке webapp создать каталог с именем resources- JSF2 знает о нем, по умолчанию он будет искать компоненты там. Внутри каталога создать еще одну папку, например mycomponents - это имя произвольное, но его нужно запомнить, т.к. оно понадобится при подключении нашего тега к странице. Внутри папки mycomponents создадим файл с описанием тега, пусть это будет simpleReportTable.xhtml. Вот его содержание:
Код

<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.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"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:composite="http://java.sun.com/jsf/composite" >

    <composite:interface name="simpleReportTable"
                         displayName="Simple Report Component">
        <composite:attribute name="model" required="true" />
    </composite:interface>

    <composite:implementation>
        <style>
            .report-title {
                font-weight: bold;
                background-color: gray;
                color: white;
            }

            .report-table,
            .report-table td
            {
                border-collapse: collapse;
                border: 1px solid gray;
                padding-left: 5px;
            }

            .report-table {
                min-width: 300px;
            }
        </style>
        <table class="report-table">
            <tr>
                <td colspan="3" class="report-title">
                    <h:outputText value="#{cc.attrs.model.reportTitle}" />
                </td>
            </tr>
            <ui:repeat value="#{cc.attrs.model.reportElements}" var="element" varStatus="status">
                <tr>
                    <td>
                        #{status.index}
                    </td>
                    <td>
                        #{element.caption}
                    </td>
                    <td>
                        #{element.value}
                    </td>
                </tr>
            </ui:repeat>
        </table>
    </composite:implementation>
</html>


Как видно, это такой же XHTML файл который можно часто увидеть при работе с Facelet-ами, но имеется небольшая особенность: теги composite:interface, где делается объявление имени и атрибутов нашего компонента; и composite:implementation который содержит разметку - реализация компонента.
Тег composite:interface в нашем случае содержит атрибуты name="simpleReportTable" и displayName="Simple Report Component". Это имя компонента и его описание. Внутри имеется тег <composite:attribute name="model" required="true" />, он объявляет что у компонента будет атрибут model, которая будет использоваться для доступа к данным необходимым для отчета. Внутри тега composite:implementation находится разметка для генерации таблицы. Доступ к атрибуту model осуществляется через конструкцию #{cc.attrs.model}, ну а свойствам модели аналогично через точку.

Чтобы использовать такой компонент на странице нашего проекта необходимо его подключить как библиотеку тегов, объявив префикс тегов. На странице index.xhtml это выглядит следующим образом (5 строка):

Код

<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:mc="http://java.sun.com/jsf/composite/mycomponents">
    <h:body>
        <mc:simpleReportTable model="#{ReportBean.reportData}" />
    </h:body>
</html>

 В пятой строке (xmlns:mc="http://java.sun.com/jsf/composite/mycomponents") мы объявляем префикс mc (можно было назвать его как угодно), url же выглядит следующим образом: стандартная приставка http://java.sun.com/jsf/composite/ + Имя папки с компонентом (mycomponents). Сам компонент имеет имя simpleReportTable, как имя файла с его реализацией. Как видно из строки 7 он имеет атрибут связанный со свойством reportData бина ReportBean.

4) Код JSF бина и классов для отчета.
Код

package com.mycompany.myjsfcomp;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

/**
 *
 * @author powerOn
 */
@RequestScoped
@ManagedBean(name="ReportBean")
public class ReportBean
{
    private ReportData reportData;

    public ReportBean()
    {
    }

    @PostConstruct
    public void init()
    {
        reportData = new ReportData("My Report Title");

        reportData.getReportElements().add(new ReportElement("Caption 1", "value 1"));
        reportData.getReportElements().add(new ReportElement("Caption 2", "value 2"));
        reportData.getReportElements().add(new ReportElement("Caption 3", "value 3"));
        reportData.getReportElements().add(new ReportElement("Caption 4", "value 4"));
        reportData.getReportElements().add(new ReportElement("Caption 5", "value 5"));
    }

    public ReportData getReportData()
    {
        return reportData;
    }

    public void setReportData(ReportData reportData)
    {
        this.reportData = reportData;
    }
}


Что интересно, в JSF 2.0 теперь можно объявлять бины с помощью аннотаций, что лично для меня является серьезным облегчением в работе.
Вспомогательные классы необходимые для отчета:
Код

package com.mycompany.myjsfcomp;

import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author powerOn
 */
public class ReportData
{
    private String reportTitle;
    private List<ReportElement> reportElements = new LinkedList<ReportElement>();

    public ReportData()
    {
    }

    public ReportData(String reportTitle)
    {
        this.reportTitle = reportTitle;
    }

    public ReportData(String reportTitle, List<ReportElement> reportElements)
    {
        this.reportTitle = reportTitle;
        this.reportElements = reportElements;
    }

    public List<ReportElement> getReportElements()
    {
        return reportElements;
    }

    public void setReportElements(List<ReportElement> reportElements)
    {
        this.reportElements = reportElements;
    }

    public String getReportTitle()
    {
        return reportTitle;
    }

    public void setReportTitle(String reportTitle)
    {
        this.reportTitle = reportTitle;
    }
}


Код

package com.mycompany.myjsfcomp;

/**
 *
 * @author powerOn
 */
public class ReportElement
{
    private String caption;
    private String value;

    public ReportElement()
    {
    }

    public ReportElement(String caption, String value)
    {
        this.caption = caption;
        this.value = value;
    }

    public String getCaption()
    {
        return caption;
    }

    public void setCaption(String caption)
    {
        this.caption = caption;
    }

    public String getValue()
    {
        return value;
    }

    public void setValue(String value)
    {
        this.value = value;
    }
}


В целом остается только собрать проект, запустить на вашем любимом сервере и открыть страницу index.xhtml. Результат должен быть примерно таким:
user posted image

Вот собственно и все, простой компонет готов. smile Конечно это лишь верхушка айсберга, многие вкусности не были затронуты, например передача в компонент не данных, а ссылки на метод и многое другое (чего я сам наверное пока не знаю smile). Если есть вопросы - welcome. 







Автор: AndrewMormysh 26.8.2009, 02:02
powerOn, всё работает, это как раз то что надо, огромное спасибо. Разбираться буду позже - тогда и вопросы задам )

P.S. а в какой среде ты программируешь? У меня IDEA 8.1 - она JSF 2.0 не признаёт. (пока писал пост - увидел в твоей подписи ссылку на NetBeans - в ней? Там всё ОКс jsf2.0?)

Автор: powerOn 26.8.2009, 07:37
NetBeans 6.8 M1 с горем пополам поддерживает JSF 2.0. По крайней мере подсказки для тегов есть. Думаю к релизу дела пойдут получше.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)