// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= Введение в JavaServer Faces 2.x
:jbake-type: tutorial
:jbake-tags: tutorials 
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: Введение в JavaServer Faces 2.x - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, Введение в JavaServer Faces 2.x

JavaServer Faces (JSF) - это платформа разработки интерфейса пользователя для веб-приложений Java. Она призвана значительно упростить процесс создания и поддержки приложений, работающих на сервере приложений Java и визуализирующих свои пользовательские интерфейсы на целевом клиенте. JSF обеспечивает простоту использования благодаря целому ряду факторов:

* упрощает формирование пользовательского интерфейса из набора повторно используемых компонентов пользовательского интерфейса;
* упрощает перенос данных приложения в пользовательский интерфейс и из него;
* помогает управлять состоянием пользовательского интерфейса при запросах к серверу;
* предоставляет простую модель установления связи между созданными клиентом событиями и кодом приложения на стороне сервера;
* упрощает сборку и повторное использование компонентов пользовательского интерфейса.

Подробное описание платформы JSF приведено в link:http://docs.oracle.com/javaee/7/tutorial/doc/jsf-develop.htm[+учебном курсе по Java EE 7, Глава 12. Разработка по технологии JavaServer Faces+].

В этом учебном курсе описывается применение поддержки JSF 2.x к веб-приложениям с помощью IDE NetBeans. Сначала необходимо добавить поддержку платформы JSF 2.x к базовому веб-приложению, а затем приступить к выполнения следующих задач:

* создать управляемый компонент JSF для обработки данных запроса,
* подключить управляемый компонент к веб-страницам приложения и
* преобразовать веб-страницы в файлы шаблонов Facelets.

IDE NetBeans обеспечивает долгосрочную поддержку для JavaServer Faces. Начиная с редакции JSF 2.0 и Java EE 6, IDE NetBeans обеспечивает поддержку для JSF 2.0 и JSF 2.1. Подробнее см. в разделе link:jsf20-support.html[+Поддержка JSF 2.x в IDE NetBeans+].



image::images/netbeans-stamp-80-74-73.png[title="Содержимое этой страницы применимо к IDE NetBeans 7.2, 7.3, 7.4 и 8.0"]


Для работы с этим учебным курсом требуются программное обеспечение и материалы, перечисленные ниже.

|===
|Программное обеспечение или материал |Требуемая версия 

|link:https://netbeans.org/downloads/index.html[+IDE NetBeans+] |7.2, 7.3, 7.4, 8.0, пакет Java EE 

|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Комплект для разработчика на языке Java (JDK)+] |7 или 8 

|link:http://glassfish.dev.java.net/[+Сервер GlassFish+] |Open Source Edition 3.x или 4 

|link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FjsfDemo.zip[+Проект веб-приложения `jsfDemo`+] |неприменимо 
|===

*Примечания*

* В комплект Java в среде IDE NetBeans также входит сервер GlassFish - сервер, совместимый с Java EE, который требуется для этого учебного курса.
* Для сравнения проекта с рабочим решением загрузите link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FjsfDemoCompleted.zip[+выполненный демонстрационный проект+].



[[support]]
== Добавление поддержки JSF 2.x к веб-приложениям

Начните работу с открытия <<requiredSoftware,проекта веб-приложения `jsfDemo`>> в среде IDE. После открытия проекта в среде IDE в него можно добавить поддержку платформы с помощью окна "Свойства" в проекте.

IDE также позволяет создавать новые проекты с поддержкой JSF 2.x. Подробнее см. раздел link:jsf20-support.html#creatingSupport[+Создание нового проекта с поддержкой JSF 2.x+].

1. Нажмите кнопку 'Открыть проект' ( image:images/open-project-btn.png[] ) на главной панели инструментов IDE или нажмите Ctrl-Shift-O (⌘-Shift-O в Mac).
2. В диалоговом окне "Открытие проекта" перейдите к папке на компьютере, в которой хранится разархивированный файл учебного проекта. Выберите его, а затем для открытия проекта в среде IDE нажмите кнопку "Открыть проект".

*Примечание.* При открытии проекта NetBeans может быть отображен запрос на разрешение ссылки на библиотеки JUnit, если при установке IDE не был установлен подключаемый модуль JUnit.


[start=3]
. Выполните проект и посмотрите, как он выглядит в браузере. Либо щелкните правой кнопкой мыши узел проекта `jsfDemo` в окне 'Проекты' и выберите 'Запустить' или нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) на главной панели инструментов. Проект запакован и разворачивается на сервере GlassFish, а в браузере открывается страница приветствия(`index.xhtml`). 

image::images/run-project.png[title="Запустите проект, чтобы просмотреть его в браузере."]

[start=4]
. Нажмите кнопку "Отправить". Страница ответа (`response.xhtml`) отображается следующим образом: 

image::images/response.png[title="Страницы приветствия и отклика в настоящее время являются статическими страницами"]

В настоящее время страницы приветствия и отклика являются статическими, и совместно с файлом `stylesheet.css` и изображением `duke.png` они являются единственными файлами приложений, доступными из браузера.


[start=5]
. В окне 'Проекты' (Ctrl-1; ⌘ -1 в Mac) щелкните правой кнопкой мыши узел проекта и выберите 'Свойства', чтобы открыть окно 'Свойства проекта'.

[start=6]
. Выберите категорию 'Платформы', а затем нажмите кнопку 'Добавить'.

[start=7]
. Выберите 'JavaServer Faces' в диалоговом окне 'Добавление платформы'. Нажмите кнопку 'ОК'. 

image::images/add-framework.png[title="Добавление поддержки JSF к существующему проекту"]

После выбора "JavaServer Faces" станут доступными различные параметры настройки. На вкладке 'Библиотеки' вы можете указать, как проект обращается к библиотекам JSF 2.x. Доступная версия JSF будет зависеть от версии IDE и сервера GlassFish. По умолчанию используются библиотеки, поставляемые с сервером (сервером GlassFish). Тем не менее, в IDE также входят библиотеки JSF 2.x. (Можно выбрать параметр "Зарегистрированные библиотеки", если их необходимо использовать в проекте).

image::images/libraries-tab.png[title="Укажите доступ к библиотекам JSF 2.x"]

[start=8]
. Выберите вкладку "Настройка". Можно указать способ регистрации сервлета Faces в дескрипторе развертывания проекта. Также можно указать, нужно ли в проекте использовать страницы Facelets или JSP. 

image::images/jsf-configuration.png[title="Укажите параметры сервлета Faces и предпочитаемый язык"]

Вы также можете легко настроить проект для использования различных наборов компонентов JSF на вкладке 'Компоненты'. Чтобы использовать набор компонентов, нужно загрузить необходимые библиотеки и использовать диспетчер Ant Library для создания новой библиотеки с библиотеками наборов компонентов.

image::images/jsf-components.png[title="Укажите параметры сервлета Faces и предпочитаемый язык"]

[start=9]
. Нажмите кнопку "ОК" для подтверждения изменений и закройте окно "Свойства проекта".

После добавления поддержки JSF к проекту дескриптор развертывания `web.xml` изменяется и выглядит следующим образом. (Изменения *выделены полужирным шрифтом*.)


[source,xml]
----

<web-app version="3.0" 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_3_0.xsd">
    *<context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</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>*
    <welcome-file-list>
        <welcome-file>*faces/*index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>
----

*Важно!* Убедитесь, что файл `web.xml` содержит только одну запись `<welcome-file>` с компонентом '`faces/`', как показано в примере. Это обеспечивает передачу страницы приветствия проекта (`index.xhtml`) через сервлет Faces перед ее отображением в браузере. Это необходимо для верного отображения компонентов библиотек тегов Facelets.

Сервлет Faces регистрируется в проекте, и теперь страница приветствия `index.xhtml` при запросе передается через сервлет Faces. Кроме того, обратите внимание, что добавлена запись для параметра контекста `PROJECT_STAGE`. При установке значения этого параметра на "`Development`" предоставляется полезная информация во время отладки приложения. См.  link:http://blogs.oracle.com/rlubke/entry/jsf_2_0_new_feature2[+http://blogs.oracle.com/rlubke/entry/jsf_2_0_new_feature2+] для получения дополнительной информации.

Для просмотра библиотек JSF разверните узел "Библиотеки" проекта в окне "Проекты". Если используются библиотеки по умолчанию, включенные в GlassFish Server 3.1.2 или GlassFish Server 4, под узлом сервера GlassFish отображается `javax.faces.jar`. (Если вы используете старую версию GlassFish, вы увидите библиотеки `jsf-api.jar` и `jsf-impl.jar`, а не `javax.faces.jar`.)

Поддержка JSF в среде IDE 2.x включает в себя в первую очередь большое количество мастеров для JSF, а также специальные функциональные возможности, предоставляемые редактором Facelets. Эти функциональные возможности описаны ниже. Подробнее см. в разделе link:jsf20-support.html[+Поддержка JSF 2.x в IDE NetBeans+].


[[managedBean]]
== Создание управляемого компонента

Управляемые компоненты JSF для обработки данных пользователя и сохранения их между запросами. Управляемый компонент – это link:http://en.wikipedia.org/wiki/Plain_Old_Java_Object[+POJO+] (простой объект Java), который используется для сохранения данных и управляется контейнером (например, сервером GlassFish) с помощью платформы JSF.

Компонент POJO по существу является классом Java, который содержит публичный безаргументный конструктор и соответствует правилам присвоения имен link:http://download.oracle.com/javase/tutorial/javabeans/[+JavaBeans+] для свойств.

При просмотре <<staticPage,статической страницы>>, полученной в результате выполнения проекта, пользователю необходим механизм, который проверяет введенное пользователем число на соответствие текущему выбранному числу и возвращает представление, соответствующее полученному результату. Чтобы создать управляемый компонент для этих целей, используйте link:jsf20-support.html#managedBean[+Мастер создания управляемого компонента+] среды IDE. Страницы Facelets, создаваемые в следующем разделе, должны иметь доступ к числу, вводимому пользователем, и к сгенерированному ответу. Для упрощения добавьте свойства `userNumber` и `response` к управляемому компоненту.

* <<usingManagedBean,Использование мастера создания управляемого компонента>>
* <<creatingConstructor,Создание конструктора>>
* <<addingProperties,Добавление свойств>>


[[usingManagedBean]]
=== Использование мастера создания управляемого компонента

1. В окне 'Проекты' щелкните правой кнопкой мыши узел проекта `jsfDemo` и выберите 'Создать' > 'Управляемый компонент JSF'. (Если "Управляемый компонент" отсутствует, выберите "Другие". Затем выберите параметр "Управляемый компонент JSF" в категории "JavaServer Faces". Нажмите кнопку "Далее".
2. В мастере введите следующее:
* *Имя класса:* UserNumberBean;
* *Пакет:* guessNumber;
* *Имя:* UserNumberBean
* *Контекст:* сеанс

image::images/managed-bean.png[title="Используйте мастер управляемых компонентов JSF для создания нового управляемого компонента"]

[start=3]
. Нажмите кнопку "Завершить". Класс `UserNumberBean` будет создан и открыт в редакторе. Обратите внимание на следующие аннотации (*выделено полужирным шрифтом*):

[source,java]
----

package guessNumber;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 *
 * @author nbuser
 */
*@ManagedBean(name="UserNumberBean")
@SessionScoped*
public class UserNumberBean {

    /** Creates a new instance of UserNumberBean */
    public UserNumberBean() {
    }

}
----

Поскольку вы используете JSF 2.x, можно объявить все относящиеся к JSF компоненты с помощью аннотаций. В предыдущих версиях их необходимо было объявлять в файле настройки Faces (`faces-config.xml`).

[tips]#Для просмотра документации Javadoc по всем аннотациям JSF 2.1 обратитесь к link:http://javaserverfaces.java.net/nonav/docs/2.1/managed-bean-javadocs/index.html[+Спецификации аннотации управляемого компонента Faces+].#


[[creatingConstructor]]
=== Создание конструктора

Конструктор `UserNumberBean` должен создавать случайное число от 0 до 10 и сохранять его в переменной экземпляра. Таким образом частично формируется бизнес-логика для приложения.

1. Определите конструктор для класса `UserNumberBean`. Введите следующий код (изменения выделены *полужирным шрифтом*).

[source,java]
----

public class UserNumberBean {

    *Integer randomInt;*

    /** Creates a new instance of UserNumberBean */
    public UserNumberBean() {
        *link:http://docs.oracle.com/javase/7/docs/api/java/util/Random.html[+Random+] randomGR = new Random();
        randomInt = new Integer(randomGR.link:http://docs.oracle.com/javase/7/docs/api/java/util/Random.html#nextInt%28int%29[+nextInt+](10));
        System.out.println("Duke's number: " + randomInt);*
    }

}
----

Вышеуказанный код создает случайное число от 0 до 10 и записывает это число в протокол сервера.


[start=2]
. Исправьте операторы импорта. Для этого щелкните метку4 подсказки ( image:images/hint-icon.png[] ), которая отображается на левой границе редактора, затем выберите параметр для импорта `java.util.Random` в класс.

[start=3]
. Повторно запустите проект (нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) или нажмите F6; fn-F6 в Mac). При выполнении проекта файл протокола сервера автоматически открывается в окне вывода. 

image::images/output1.png[title="Файл журнала сервера автоматически открывается в окне вывода."]

Обратите внимание на то, что в окне вывода не отображается "`Номер Дюка: `" (как указывалось в конструкторе). Объект `UserNumberBean` не создан, так как по умолчанию в JSF используется _"ленивое" создание экземпляра_. Таким образом, компоненты в определенных контекстах создаются и инициализируются, только если они необходимы в приложении.

Состояния link:http://javaserverfaces.java.net/nonav/docs/2.1/managed-bean-javadocs/index.html[+Документации Javadoc по аннотации `@ManagedBean`+]:

_Если атрибут `eager()` имеет значение `true`, а значением `managed-bean-scope` является "application", то в среде выполнения при запуске приложения должен быть создан экземпляр этого класса. Создание и сохранение экземпляра должно осуществляться до обслуживания запросов. Если атрибут _eager_ не указан либо имеет значение `false` или элементу `managed-bean-scope` не присвоено значение "приложение", по умолчанию происходит "ленивое" создание экземпляра и контекстное сохранение управляемого компонента._

[start=4]
. Поскольку класс `UserNumberBean` входит в контекст сеанса, реализуется интерфейс `Serializable`.

[source,java]
----

@ManagedBean(name="UserNumberBean")
@SessionScoped
public class UserNumberBean *implements Serializable* {
----
Используйте метку подсказки ( image:images/hint-icon.png[] ) для импорта `java.io.Serializable` в класс.


[[addingProperties]]
=== Добавление свойств

Страницы Facelets, создаваемые в следующем разделе, должны иметь доступ к числу, вводимому пользователем, и к сгенерированному ответу. Для упрощения этого добавьте свойства `userNumber` и `response` к классу.

1. Начните с объявления `Integer` с именем `userNumber`.

[source,java]
----

@ManagedBean(name="UserNumberBean")
@SessionScoped
public class UserNumberBean implements Serializable {

    Integer randomInt;
    *Integer userNumber;*
----

[start=2]
. Щелкните правой кнопкой мыши в редакторе и выберите команду "Вставить код" (ALT+INS; CTRL+I на компьютере Mac). Выберите методы получения и установки. 

image::images/getter-setter.png[title="Используйте IDE для создания методов доступа для свойств"]

[start=3]
. Выберите параметр `userNumber`: `Integer`. Нажмите кнопку "Создать". 

image::images/generate-getters-setters.png[title="Используйте IDE для создания методов доступа для свойств"]

Обратите внимание на то, что методы `getUserNumber()` и `setUserNumber(Integer userNumber)` добавлены в класс.


[start=4]
. Создайте свойство `response`. Объявите `String` с именем `response`.

[source,java]
----

@ManagedBean(name="UserNumberBean")
@SessionScoped
public class UserNumberBean implements Serializable {

    Integer randomInt;
    Integer userNumber;
    *String response;*
----

[start=5]
. Создайте метод получения для `response`. (Для этого приложения не требуется метод установки). Для создания кода шаблона в среде IDE можно использовать всплывающее окно "Создание кода", упомянутое выше в действии 2. Однако в целях изучения данного руководства просто вставьте нижеуказанный метод в класс.

[source,html]
----

public String getResponse() {
    if ((userNumber != null) &amp;&amp; (userNumber.link:http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html#compareTo(java.lang.Integer)[+compareTo+](randomInt) == 0)) {

        //invalidate user session
        FacesContext context = FacesContext.getCurrentInstance();
        HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
        session.invalidate();

        return "Yay! You got it!";
    } else {

        return "<p>Sorry, " + userNumber + " isn't it.</p>"
                + "<p>Guess again...</p>";
    }
}
----
Вышеуказанный метод выполняет две функции.
1. Тестирует введенное пользователем число (`userNumber`) на равенство случайному числу, сгенерированному для сеанса (`randomInt`), и возвращает соответствующий ответ `String`.
2. Определяет пользовательский сеанс как недействительный, если пользователь ввел правильное число (т.е., если `userNumber` равно `randomInt`). Это необходимо для того, чтобы новое сгенерированное число побудило пользователя сыграть еще раз.

[start=6]
. Щелкните правой кнопкой мыши в области редактора и выберите команду "Исправить операторы импорта" (ALT+SHIFT+I; &amp;#8984+SHIFT+I на компьютере Mac). Параметры импорта автоматически создаются для:
* `javax.servlet.http.HttpSession`
* `javax.faces.context.FacesContext`

Можно нажать сочетание клавиш CTRL+ПРОБЕЛ на элементах в редакторе для вызова предложений автозавершения кода и поддержки документации. Нажмите сочетание клавиш CTRL+ПРОБЕЛ, установив курсор на `FacesContext`, для просмотра описания класса из документации Javadoc.


image::images/documentation-support.png[title="Для вызова поддержки автозавершения кода и документации нажмите сочетание клавиш CTRL+ПРОБЕЛ."] 

Щелкните значок веб-браузера ( image:images/web-browser-icon.png[] ) в окне документации, чтобы открыть Javadoc во внешнем веб-браузере.



[[wire]]
== Установление связи между управляемым компонентом и страницами

Одной из первичных целей JSF является отмена необходимости записывать шаблонный код для управления объектами <<pojo,POJO>> и их взаимодействием с видами приложений. Пример этого был приведен в предыдущем разделе, в котором JSF создал объект `UserNumberBean` при выполнении приложения. Это представление называется link:http://martinfowler.com/articles/injection.html[+Инверсия управления+] (IoC). Оно позволяет контейнеру принимать на себя ответственность за управление частями приложения, иначе разработчику потребовалось бы написать код с повторениями.

В предыдущем разделе был создан управляемый компонент, генерирующий случайное число от 0 до 10. Также было создано два свойства `userNumber` и `response`, представляющие соответственно пользовательский ввод числа и ответ на вопрос пользователя.

В этом разделе показаны способы использования `UserNumberBean` и его свойств на веб-страницах. JSF позволяет это сделать с помощью языка выражения. Язык выражения используется для привязки значений свойств к компонентам пользовательского интерфейса JSF, содержащихся на веб-страницах приложений. В этом разделе также показано, как можно воспользоваться внутренними функциями навигации JSF 2.x для перемещения между индексом и страницами ответов.

Эта поддержка в среде IDE обеспечивается с помощью функции автозавершения кода и средств документации, которые вызываются нажатием сочетания клавиш CTRL+ПРОБЕЛ, когда курсор установлен на каком-либо элементе в редакторе.

Начните с внесения изменений в `index.xhtml`, затем измените `response.xhtml`. На обеих страницах замените элементы формы HTML их эквивалентами JSF, поскольку они определены в link:http://javaserverfaces.java.net/nonav/docs/2.1/vdldocs/facelets/index.html[+библиотеке тегов HTML для JSF+]. Затем используйте язык выражений JSF для привязки значений свойств к выбранным компонентам пользовательского интерфейса.

* <<index,index.xhtml>>
* <<response,response.xhtml>>


[[index]]
=== index.xhtml

1. Откройте страницу `index.xhtml` в редакторе. Дважды щелкните узел `index.xhtml` в окне "Проекты" или нажмите сочетание клавиш ALT+SHIFT+O для открытия диалогового окна "Переход к файлу". 

Как индекс, так и страницы ответов уже содержат компоненты пользовательского интерфейса JSF, необходимые для этого упражнения. Просто раскомментируйте их и закомментируйте элементы HTML, используемые в настоящий момент.

[start=2]
. Закомментируйте элемент формы HTML. Для этого выделите элемент формы HTML, как показано на изображении ниже, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac). 

*Примечание. *Для выделения воспользуйтесь функцией перетаскивания в редакторе с помощью мыши или с помощью клавиатуры удерживайте клавишу Shift и используйте клавиши со стрелками. 

image::images/comment-out.png[title="Выделите код, затем нажмите Ctrl-/ для закомментирования кода"]

Для переключения комментариев нажмите сочетание клавиш CTRL+/ (&amp;#8984+/ на компьютере Mac). Эту комбинацию клавиш также можно использовать для других типов файлов, например, Java и CSS.


[start=3]
. Раскомментируйте компонент формы HTML для JSF. Выделите этот компонент, как показано на рисунке ниже, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac).

*Примечание.* Возможно, вам придется нажать Ctrl-/ дважды, чтобы раскомментировать код.


image::images/comment.png[title="Выделите закомментированный код, затем нажмите Ctrl-/ для удаления комментария"]

После того как компонент формы HTML для JSF раскомментирован, в редакторе будет указано, что теги `<h:form>`, `<h:inputText>` и `<h:commandButton>` не объявлены.

image::images/undeclared-component.png[title="Редактор обеспечивает сообщения об ошибках для необъявленных компонентов"]

[start=4]
. Для объявления этих компонентов используйте автозавершение кода IDE, чтобы добавить пространство имен библиотеки тегов в тег `<html>` страницы. Наведите курсор на любой из необъявленных тегов, нажмите Alt-Enter и нажмите Enter, чтобы добавить предложенные библиотеки тегов. (При наличии нескольких параметров перед нажатием клавиши ВВОД убедитесь, что выбран тег, отображаемый в редакторе.) Пространство имен библиотеки тегов HTML для JSF добавляется к тегу `<html>` (*выделено ниже полужирным шрифтом*), и указания на ошибки исчезают.

*Примечание.* Если в IDE нет возможности добавить библиотеку тегов, потребуется вручную изменить элемент  ``<html>`` .


[source,java]
----

<html xmlns="http://www.w3.org/1999/xhtml"
      *xmlns:h="http://xmlns.jcp.org/jsf/html"*>
----

[start=5]
. Используйте язык выражения JSF для привязки свойства `userNumber` для `UserNumberBean` к компоненту `inputText`. Атрибут `value` используется для указания текущего значения визуализируемого компонента. Введите в код, отображаемый ниже *полужирным шрифтом*.

[source,java]
----

<h:form>
    <h:inputText id="userNumber" size="2" maxlength="2" *value="#{UserNumberBean.userNumber}"* />
----

В языке выражения JSF используется синтаксис `#{}`. Внутри этих парных символов указывается имя требуемого управляемого компонента и его свойство, разделенные точкой (`.`). Теперь при отправке данных формы на сервер значение автоматически сохраняется в свойстве `userNumber` с помощью метода установки свойств (`setUserNumber()`). Кроме того, если страница запрошена и значение для `userNumber` уже установлено, значение автоматически отображается в визуализированном компоненте `inputText`. Дополнительные сведения приведены в link:http://docs.oracle.com/javaee/7/tutorial/doc/jsf-develop001.htm#BNAQP[+Руководстве по Java EE 7. Глава 12.1.2 Использование языка выражений для создания ссылок на управляемые сеансные объекты+].


[start=6]
. Укажите адресата для запроса, который вызывается при нажатии кнопки формы. В HTML-версии формы это возможно выполнить с помощью атрибута `action` тега `<form>`. С помощью JSF можно использовать атрибут `action` для `commandButton`. Кроме того, благодаря внутренней функции навигации JSF 2.x вам нужно только указать имя конечного файла без расширения.

Введите код, отображаемый ниже *полужирным шрифтом*.


[source,xml]
----

<h:form>
    <h:inputText id="userNumber" size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />
    <h:commandButton id="submit" value="submit" *action="response"* />
</h:form>
----

В среде выполнения JSF осуществляется поиск файла с именем `response`. Предполагается, что расширение файла такое же, как у файла, из которого произошел запрос (`index*.xhtml*`), и поиск файла `response.xhtml` выполняется в папке исходного файла (т.е. в корневом веб-узле).

*Примечание. *JSF 2.x позволяет упростить разработку. При использовании JSF 1.2 для этого проекта необходимо объявить правило перехода в файле настройки Faces. Объявление правила может выглядеть следующим образом:


[source,xml]
----

<navigation-rule>
    <from-view-id>/index.xhtml</from-view-id>

    <navigation-case>
        <from-outcome>response</from-outcome>
        <to-view-id>/response.xhtml</to-view-id>
    </navigation-case>
</navigation-rule>
----

Нижеприведенные действия с 7 по 12 являются дополнительными. Если необходимо выполнить быструю сборку проекта, сразу перейдите к <<response,`response.xhtml`>>.


[start=7]
. Протестируйте, выполняется ли вызов метода `setUserNumber()` вышеуказанным выражением на языке выражения при обработке запроса. Для выполнения этого используйте отладчик Java среды IDE.

Переключите на класс `UserNumberBean` (нажмите сочетание клавиш CTRL+TAB и выберите из списка файл). Установите точку останова в сигнатуре метода `setUserNumber()`. Это можно сделать, щелкнув мышкой в области левого поля. Появится красный значок, указывающий, что точка останова метода установлена.

image::images/set-breakpoint.png[title="Щелкните левую границу редактора для задания точек останова"]

[start=8]
. Нажмите кнопку 'Отладка проекта' (image:images/breakpoint-btn.png[]) на главной панели инструментов IDE. Начинается сеанс отладки, и в браузере открывается страница приветствия проекта.

*Примечания.*

* Вам может быть предложено подтвердить порт сервера для отладки приложений.
* Если появится диалоговое окно 'Отладить проект', выберите опцию по умолчанию 'Java на стороне сервера' и нажмите кнопку 'Отладка'.

[start=9]
. В браузере введите номер в форму и нажмите кнопку "Отправить".

[start=10]
. Вернитесь в среду IDE и проверьте класс `UserNumberBean`. Отладчик приостановлен в методе `setUserNumber()`. 

image::images/debugger-suspended.png[title="Выполняется приостановка отладчика в соответствии с точками останова"]

[start=11]
. Откройте окно "Переменные отладчика" (выберите "Окно" > "Отладка > "Переменные" или нажмите сочетание клавиш CTRL+SHIFT+1). На экран будут выведены значения переменных для точки, в которой приостановлен отладчик. 

image::images/variables-window.png[title="Отслеживание значений переменных с помощью окна 'Переменные отладчика'"]

На приведенном выше изображении значение "`4`" предоставлено для переменной `userNumber` в сигнатуре `setUserNumber()`. (Число 4 введено в форму.) "`this`" относится к объекту `UserNumberBean`, созданному для пользовательского сеанса. Далее можно отметить, что значение свойства `userNumber` в настоящий момент равно `null`.


[start=12]
. На панели отладчика нажмите кнопку 'Вход в' ( image:images/step-into-btn.png[] ). Отладчик выполняет обработку строки, на которой он в настоящий момент приостановлен. Происходит обновление окна "Переменные" с указанием выполненных изменений. 

image::images/variables-window2.png[title="Окно переменных обновляется при переходе по коду"] 

Теперь свойству `userNumber` присвоено значение, введенное в форме.


[start=13]
. Выберите Отладка> Завершить сеанс отладки (Shift-F5; Shift-Fn-F5 на Mac) из главного меню, чтобы остановить отладчик.


[[response]]
=== response.xhtml

1. Откройте страницу `response.xhtml` в редакторе. В окне "Проекты" дважды щелкните узел `response.xhtml` или нажмите сочетание клавиш ALT+SHIFT+O для открытия диалогового окна "Переход к файлу".
2. Закомментируйте элемент формы HTML. Выделите открывающий и закрывающий теги HTML `<form>` и код между ними, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac).

*Примечание: * Для выделения воспользуйтесь функцией перетаскивания в редакторе с помощью мыши или с помощью клавиатуры удерживайте клавишу Shift и используйте клавиши со стрелками.


[start=3]
. Раскомментируйте компонент формы HTML для JSF. Выделите открывающий и закрывающий теги `<h:form>` и код между ними, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac).

На данном этапе, код между тегами `<body>` выглядит следующим образом:


[source,html]
----

<body>
    <div id="mainContainer">

        <div id="left" class="subContainer greyBox">

            <h4>[ response here ]</h4>

            <!--<form action="index.xhtml">

                <input type="submit" id="backButton" value="Back"/>

            </form>-->

            <h:form>

                <h:commandButton id="backButton" value="Back" />

            </h:form>

        </div>

        <div id="right" class="subContainer">

            <img src="duke.png" alt="Duke waving" />
             <!--<h:graphicImage url="/duke.png" alt="Duke waving" />-->

        </div>
    </div>
</body>
----

После того как компонент формы HTML для JSF раскомментирован, в редакторе будет указано, что теги `<h:form>` и `<h:commandButton>` не объявлены.


[start=4]
. Для объявления этих компонентов используйте автозавершение кода IDE, чтобы добавить пространство имен библиотеки тегов в тег `<html>` страницы.

Используйте поддержку автозавершения кода в редакторе для добавления необходимых пространств имен JSF к файлу. При выборе тега JSF или Facelets через автозавершение кода происходит автоматическое добавление требуемого пространства имен к корневому элементу документа. Подробнее см. в разделе link:jsf20-support.html#facelets[+Поддержка JSF 2.x в IDE NetBeans+].

Установите курсор на один из необъявленных тегов и нажмите сочетание клавиш CTRL+ПРОБЕЛ. Предложения автозавершения кода и отображения поддержки документации.

image::images/code-completion2.png[title="Для вызова рекомендаций по автозавершению кода и всплывающего окна документации"]

Нажмите ENTER. (При наличии нескольких параметров перед нажатием клавиши ВВОД убедитесь, что выбран тег, отображаемый в редакторе.) Пространство имен библиотеки тегов HTML для JSF добавляется к тегу `<html>` (*выделено ниже полужирным шрифтом*), и указания на ошибки исчезают.


[source,java]
----

<html xmlns="http://www.w3.org/1999/xhtml"
      *xmlns:h="http://xmlns.jcp.org/jsf/html"*>
----

[start=5]
. Укажите адресата для запроса, который вызывается при нажатии пользователем кнопки формы. Кнопку необходимо установить так, чтобы при ее нажатии пользователь возвращался на страницу-указатель. Для этого следует использовать атрибут `action` для `commandButton`. Введите в код, отображаемый *полужирным шрифтом*.

[source,xml]
----

<h:form>

    <h:commandButton id="backButton" value="Back" *action="index"* />

</h:form>
----

*Примечание. * При вводе `action="index"` пользователи в работе зависят от функции явной навигации в JSF. При нажатии кнопки формы в среде выполнения JSF осуществляется поиск файла с именем `index`. Предполагается, что расширение файла такое же, как у файла, от которого был направлен запрос (`response*.xhtml*`), и поиск файла `index.xhtml` выполняется в папке исходного файла (т.е. в корневом веб-узле).


[start=6]
. Замените статический текст "[здесь ответ]" значением свойства `response` для `UserNumberBean`. Для этого используйте язык выражения JSF. Введите следующее (*выделено полужирным шрифтом*).

[source,html]
----

<div id="left" class="subContainer greyBox">

    <h4>*<h:outputText value="#{UserNumberBean.response}"/>*</h4>
----

[start=7]
. Запустите проект (нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) или нажмите F6; fn-F6 в Mac). При появлении в браузере страницы приветствия введите номер и нажмите `submit`. Страница ответа будет отображаться следующим образом (выводится на экран, если введен неправильный номер). 

image::images/response2.png[title="Просмотрит текущее состояния проекта в браузере"]

Две ошибки в текущем состоянии страницы ответа:

1. Теги HTML `<p>` отображаются в ответном сообщении.
2. Кнопка "Назад" не отображается в правильном местоположении. (Сравните с <<originalVersion,исходной версией>>.)

При выполнении следующих двух шагов эти ошибки устраняются.


[start=8]
. Установите атрибут `escape` тега `<h:outputText>` на `false`. Установите курсор между `outputText` и `value`, вставьте пробел и нажмите сочетание клавиш CTRL+ПРОБЕЛ для вызова автозавершения кода. Прокрутите вниз для выбора атрибута `escape` и проверки документации. 

image::images/escape-false.png[title="Нажмите Ctrl-Пробел для просмотра возможных значений атрибутов и документации"]

Как указано в документации, значение `escape` установлено по умолчанию на `true`. Это означает, что символы, которые стандартно анализируются как html, включены в строку, как указано выше. Установка значения на `false` означает, что символы, анализируемые как HTML, можно визуализировать как HTML.

Нажмите ENTER, затем в качестве значения введите `false`.


[source,xml]
----

<h4><h:outputText *escape="false"* value="#{UserNumberBean.response}"/></h4>
----

[start=9]
. Установите атрибут `prependId` тега `<h:form>` на `false`. Установите курсор сразу после "`m`" в `<h:form>` и вставьте пробел, затем нажмите сочетание клавиш CTRL+ПРОБЕЛ для вызова автозавершения кода. Прокрутите вниз для выбора атрибута `prependId` и проверки документации. Затем нажмите ENTER и в качестве значения введите `false`.

[source,java]
----

<h:form *prependId="false"*>
----

В JSF применяются внутренние идентификаторы для отслеживания компонентов пользовательского интерфейса. В текущем примере при проверке исходного кода визуализируемой страницы отображается следующее:


[source,xml]
----

<form id="j_idt5" name="j_idt5" method="post" action="/jsfDemo/faces/response.xhtml" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt5" value="j_idt5" />
    <input *id="j_idt5:backButton"* type="submit" name="j_idt5:backButton" value="Back" />
    <input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="7464469350430442643:-8628336969383888926" autocomplete="off" />
</form>
----

Идентификатором элемента формы является `j_idt5`, и этот идентификатор _предшествует_ идентификатору кнопки "Назад", включенной в форму (*выделено полужирным шрифтом* в приведенном выше примере). Поскольку кнопка "Назад" зависит от правила стиля `#backButton` (определенного в `stylesheet.css`), это правило становится блокированным, если идентификатор JSF предшествует идентификатору кнопки. Этого можно избежать, если для `prependId` установить значение `false`.


[start=10]
. Повторно запустите проект (нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) или нажмите F6; fn-F6 в Mac). Введите число на странице приветствия, затем нажмите кнопку "Отправить". Теперь на странице ответа отображается ответное сообщение без тегов `<p>`, и кнопка "Назад" размещена правильно. 

image::images/response3.png[title="Просмотрит текущее состояния проекта в браузере"]

[start=11]
. Нажмите кнопку "Назад". Поскольку текущее значение свойства `userNumber` для `UserNumberBean` привязано к компоненту `inputText` JSF, ранее введенное число теперь отображается в текстовом поле.

[start=12]
. Проверьте протокол сервера в окне вывода среды IDE (CTRL+4; &amp;#8984+4 на компьютере Mac) для определения правильного загаданного числа.

Если по каким-то причинам просмотреть протокол сервера невозможно, откройте его посредством переключения на окно "Службы" (CTRL+5; &amp;#8984+5 на компьютере Mac) и развертывания узла "Серверы". Затем щелкните правой кнопкой мыши сервер GlassFish, на котором развернут проект и выберите 'Просмотреть журнал сервера'. Если номер не отображается в журнале сервера, попробуйте повторно выполнить сборку приложения, щелкнув правой кнопкой мыши узел проекта и выбрав 'Очистка и сборка'.


[start=13]
. Введите правильное число и нажмите кнопку "Отправить". В приложении происходит сравнение введенного числа с текущим сохраненным числом и выводится соответствующее сообщение. 

image::images/yay.png[title="При вводе соответствующего числа отображается правильный отклик"]

[start=14]
. Нажмите еще раз кнопку "Назад". Обратите внимание на то, что ранее введенное число более не отображается в текстовом поле. Следует помнить о том, что метод `getResponse()` для `UserNumberBean` <<getResponse,определяет текущий пользовательский сеанс как недействительный>> при угадывании правильного числа.



[[template]]
== Применение шаблона Facelets

Facelets сегодня является стандартной технологией отображения для JSF 2.x. Facelets - это облегченная платформа шаблонов, которая поддерживает все компоненты JSF пользовательского интерфейса и используется для построения и визуализации дерева компонентов JSF для просмотра приложений. Кроме того, эта технология обеспечивает поддержку разработки при возникновении ошибок языка выражений за счет возможности проверять трассировку стека, дерево компонентов и контекстные переменные.

Хотя, возможно, вы об этом не задумывались, файлы `index.xhtml` и `response.xhtml`, с которыми вы работаете в этом руководстве, являются страницами Facelets. Страницы Facelets имеют расширение `.xhtml` и, поскольку вы работаете в проекте JSF 2.x (библиотеки JSF 2.x включают в себя файлы JAR Facelets), эти представления способны надлежащим образом визуализировать дерево компонентов JSF.

Целью этого раздела является знакомство с созданием шаблона Facelets. Для проектов с несколькими представлениями зачастую полезно применять файл шаблона, определяющего структуру и внешний вид для нескольких представлений. При обслуживании запросов приложение вставляет динамически подготовленное содержимое во временный файл и отправляет результат обратно клиенту. Хотя данный проект имеет только два представления (страницу приветствия и страницу ответа), можно легко отметить, что большая часть содержимого в них дублируется. Это дублированное содержимое можно перенести в шаблон Facelets и создать файлы клиента шаблона для обработки содержимого, которое является специфичным для страницы приветствия и страницы ответа.

В среде IDE существует link:jsf20-support.html#faceletsTemplate[+мастер создания шаблона Facelets+] для создания шаблонов Facelets и мастер создания клиента шаблона Facelets для создания файлов, зависящих от шаблона. В этом разделе описано использование этих мастеров.

*Примечание.* IDE также предоставляет мастер страниц JSF, что позволяет создавать индивидуальные страницы Facelets для проекта. Подробнее см. в разделе link:jsf20-support.html#jsfPage[+Поддержка JSF 2.x в IDE NetBeans+].

* <<templateFile,Создание файла шаблона Facelets>>
* <<templateClient,Создание файлов клиента шаблона>>


[[templateFile]]
=== Создание файла шаблона Facelets

1. Создайте файл шаблона Facelets. Нажмите сочетание клавиш CTRL+N (&amp;#8984+N на компьютере Mac) для открытия мастера создания файлов. Выберите категорию "JavaServer Faces", затем "Шаблон Facelets". Нажмите кнопку "Далее".
2. В поле "Имя файла" введите `template`.
3. Выберите один из восьми стилей размещения и нажмите кнопку "Готово". (Вы будете использовать существующую таблицу стилей, так что не имеет значения, какой стиль вы выберете.) 

image::images/layout-style.png[title="Мастер шаблонов Facelets позволяет сделать выбор из распространенных стилей компоновки"] 

Мастером будут созданы файл `template.xhtml` и сопутствующие таблицы стилей на основе выбора, которые будут помещены в папку `resources` > `css` в корневом веб-узле проекта.

После завершения выполнения мастера в редакторе открывается файл шаблона. Для просмотра шаблона в браузере, щелкните правой кнопкой мыши в редакторе и выберите 'Просмотр'.


[start=4]
. Проверьте разметку файла шаблона. Обратите внимание на следующие моменты.
* Библиотека тегов `facelets` объявлена в теге `<html>` страницы. Библиотека тегов имеет префикс `ui`.

[source,java]
----

<html xmlns="http://www.w3.org/1999/xhtml"
      *xmlns:ui="http://xmlns.jcp.org/jsf/facelets"*
      xmlns:h="http://xmlns.jcp.org/jsf/html">
----
* На странице Facelets используются теги `<h:head>` и `<h:body>` вместо тегов HTML `<head>` и `<body>`. При использовании этих тегов у Facelets появляется возможность создания дерева компонентов, которое включает в себя всю страницу.
* Страница ссылается на таблицы стилей, которые также создаются при завершении выполнения мастера.

[source,xml]
----

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    *<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />*
    *<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />*
    <title>Facelets Template</title>
</h:head>
----
* Теги `<ui:insert>` используются в теле страницы для каждого раздела, связанного с выбранным стилем размещения. Каждый тег `<ui:insert>` имеет атрибут `name`, определяющий раздел. Например:

[source,html]
----

<div id="top">
    *<ui:insert name="top">Top</ui:insert>*
</div>
----

[start=5]
. Повторно проверьте страницу <<staticPage,приветствия>> и страницу <<responsePage,ответа>>. Содержимым, которое изменяется на этих страницах, является только заголовок и текст в сером квадрате. Следовательно, шаблон может включать в себя все остальное содержимое.

[start=6]
. Замените все содержимое файла шаблона содержимым, приведенным ниже.

[source,html]
----

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link href="css/stylesheet.css" rel="stylesheet" type="text/css" />

        <title><ui:insert name="title">Facelets Template</ui:insert></title>
    </h:head>

    <h:body>

        <div id="left">
            <ui:insert name="box">Box Content Here</ui:insert>
        </div>

    </h:body>

</html>
----
Приведенный выше код реализует следующие изменения.
* Файл `stylesheet.css` проекта заменяет ссылки на таблицу стилей шаблона, созданные в мастере.
* Все теги `<ui:insert>` (вместе с тегами `<div>`) удаляются за исключением одного с именем `box`.
* В теги `<ui:insert>` вставляется заголовок страницы с именем `title`.

[start=7]
. Скопируйте в шаблон соответствующий код из файла `index.xhtml` или файла `response.xhtml`. Добавьте содержимое, отображаемое ниже *полужирным шрифтом*, в теги `<h:body>` файла шаблона.

[source,html]
----

<h:body>
    *<div id="mainContainer">*
        <div id="left" *class="subContainer greyBox"*>
            <ui:insert name="box">Box Content Here</ui:insert>
        </div>
        *<div id="right" class="subContainer">
            <img src="duke.png" alt="Duke waving" />
        </div>
    </div>*
</h:body>
----

[start=8]
. Выполните проект. При открытии страницы приветствия в браузере измените URL-адрес на следующий:

[source,java]
----

http://localhost:8080/jsfDemo/faces/template.xhtml
----
Файл шаблона отображается следующим образом: 

image::images/facelets-template.png[title="Просмотрите шаблон Facelets в браузере"]

Теперь проект включает в себя файл шаблона, предоставляющий внешний вид и структуру всех представлений. Теперь можно создавать файлы клиента для вызова шаблона.


[[templateClient]]
=== Создание файлов клиента шаблона

Создайте файлы клиента шаблона для страниц приветствия и ответа. Укажите имя файла клиента шаблона для страницы приветствия `greeting.xhtml`. Для страницы ответа – файл `response.xhtml`.


==== greeting.xhtml

1. Нажмите сочетание клавиш CTRL+N (⌘-N на компьютере Mac) для открытия мастера создания файлов. Выберите категорию "JavaServer Faces", затем "Клиент шаблона Facelets". Нажмите кнопку "Далее".
2. В поле "Имя файла" введите `greeting`.
3. Нажмите кнопку "Обзор" рядом с полем "Шаблон", затем в открывшемся диалоговом окне перейдите к файлу `template.xhtml`, созданному в предыдущем разделе. 

image::images/template-client.png[title="Мастер создания клиентов шаблона Facelets"]

[start=4]
. Нажмите кнопку "Завершить". Будет создан новый файл клиента шаблона `greeting.xhtml`, который откроется в редакторе.

[start=5]
. Проверьте разметку. Обратите внимание на содержимое, выделенное *полужирным шрифтом*.

[source,xml]
----

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">

    <body>

        <ui:composition *template="./template.xhtml"*>

            <ui:define *name="title"*>
                title
            </ui:define>

            <ui:define *name="box"*>
                box
            </ui:define>

        </ui:composition>

    </body>
</html>
----
Файл клиента шаблона ссылается на шаблон с помощью атрибута `template` тега `<ui:composition>`. Поскольку шаблон содержит теги `<ui:insert>` для `title` и `box`, клиент шаблона содержит теги `<ui:define>` для этих двух имен. Содержимое, указываемое в тегах `<ui:define>`, - это содержимое, вставляемое в шаблон в тегах `<ui:insert>` соответствующего имени.

[start=6]
. Укажите `greeting` в качестве заголовка файла. Внесите следующее изменение, выделенное *полужирным шрифтом*.

[source,xml]
----

<ui:define name="title">
    *Greeting*
</ui:define>
----

[start=7]
. Перейдите к файлу `index.xhtml` (нажмите CTRL+TAB) и скопируйте содержимое, которое обычно появляется в сером квадрате, выведенном на визуализируемой странице. Затем обратно переключитесь на файл `greeting.xhtml` и вставьте его в файл клиента шаблона. (Изменения *выделены полужирным шрифтом*.)

[source,xml]
----

<ui:define name="box">
    *<h4>Hi, my name is Duke!</h4>

    <h5>I'm thinking of a number

        <br/>
        between
        <span class="highlight">0</span> and
        <span class="highlight">10</span>.</h5>

    <h5>Can you guess it?</h5>

    <h:form>
        <h:inputText size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />
        <h:commandButton id="submit" value="submit" action="response" />
    </h:form>*
</ui:define>
----

[start=8]
. Объявите библиотеку тегов HTML JSF для файла. Установите курсор на один из тегов, помеченных флагом ошибки (любой тег с префиксом "`h`"), и нажмите сочетание клавиш CTRL+ПРОБЕЛ. Затем выберите тег из списка предложений автозавершения кодов. Пространство имен библиотеки тегов добавляется к тегу `<html>` файла (выделено ниже *полужирным шрифтом*), и указания на ошибки исчезают.

[source,java]
----

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      *xmlns:h="http://xmlns.jcp.org/jsf/html"*>
----

При установке курсора после "`m`" в `<h:form>` и нажатии сочетания клавиш CTRL+ПРОБЕЛ к файлу автоматически добавляется пространство имен. Если при нажатии сочетания клавиш CTRL+ПРОБЕЛ доступен только один логический параметр, он немедленно применяется к файлу. Библиотека тегов JSF автоматически объявляется при вызове автозавершения кода в тегах.


==== response.xhtml

Поскольку проект уже содержит файл с именем `response.xhtml` и известно, как теперь должен выглядеть файл клиента шаблона, измените существующий файл `response.xhtml`, чтобы получить соответствующий файл клиента шаблона. (В целях данного руководства просто скопируйте и вставьте предоставленный код.)

1. Откройте файл `response.xhtml` в редакторе. (Если он уже открыт, нажмите CTRL+TAB и выберите его). Замените содержимое всего файла нижеприведенным кодом.

[source,xml]
----

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

    <body>

        <ui:composition template="./template.xhtml">

            <ui:define name="title">
                Response
            </ui:define>

            <ui:define name="box">
                <h4><h:outputText escape="false" value="#{UserNumberBean.response}"/></h4>

                <h:form prependId="false">

                    <h:commandButton id="backButton" value="Back" action="greeting" />

                </h:form>
            </ui:define>

        </ui:composition>

    </body>
</html>
----
Обратите внимание на то, что файл идентичен файлу `greeting.xhtml`, за исключением содержимого, указанного в тегах `<ui:define>` для `title` и `box`.

[start=2]
. В дескрипторе развертывания `web.xml` проекта измените запись файла приветствия таким образом, чтобы при запуске приложения открывалась страница, представленная файлом `greeting.xhtml`. 

В окне 'Проекты' дважды щелкните 'Файлы конфигурации' > `web.xml`, чтобы открыть его в редакторе. На вкладке "Страницы" измените поле "Файлы приветствия" на `faces/greeting.xhtml`. 

image::images/welcome-files.png[title="Измените запись 'Файлы приветствия' в дескрипторе развертывания"]

[start=3]
. Выполните проект и посмотрите, как он выглядит в браузере. Нажмите F6 (fn-F6 в Mac) или нажмите кнопку 'Запустить проект'( image:images/run-project-btn.png[] ) на главной панели инструментов. Проект будет развернут на сервере GlassFish и открыт в браузере.

При использовании шаблона Facelets и файлов клиента шаблона поведение приложения не меняется. Выделив повторяющийся код на страницах приветствия и ответа приложения, можно уменьшить размер приложения и устранить возможность написания повторяющегося кода, если впоследствии будут добавляться другие страницы. Это позволяет сделать разработку более эффективной и упростить управление при работе с большими проектами.

link:/about/contact_form.html?to=3&subject=Feedback:%20Introduction%20to%20JSF%202.0[+Отправить отзыв по этому учебному курсу+]



[[seealso]]
== Дополнительные сведения

Подробнее о JSF 2.x см. в следующих ресурсах.


=== Статьи и учебные курсы по NetBeans

* link:jsf20-support.html[+Поддержка JSF 2.x в IDE NetBeans+]
* link:jsf20-crud.html[+Создание приложения JavaServer Faces 2.x CRUD на основе базы данных+]
* link:../../samples/scrum-toys.html[+Scrum Toys – полный пример приложения JSF 2.0+]
* link:../javaee/javaee-gettingstarted.html[+Начало работы с приложениями Java EE+]
* link:../../trails/java-ee.html[+Учебная карта по Java EE и Java Web+]


=== Внешние ресурсы

* link:http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[+Технология JavaServer Faces+] (официальная домашняя страница)
* link:http://jcp.org/aboutJava/communityprocess/final/jsr314/index.html[+Спецификация JSR 314 для JavaServer Faces 2.0+]
* link:http://docs.oracle.com/javaee/7/tutorial/doc/jsf-develop.htm[+Учебный курс по Java EE 7. Глава 12. Разработка по технологии JavaServer Faces+]
* link:http://javaserverfaces.dev.java.net/[+GlassFish Project Mojarra+] (официальный пример реализации JSF 2.х)
* link:http://forums.oracle.com/forums/forum.jspa?forumID=982[+Интернет-форум OTN: JavaServer Faces+]
* link:http://www.jsfcentral.com/[+JSF Central+]


=== Блоги

* link:http://www.java.net/blogs/edburns/[+Эд Бернс (Ed Burns)+]
* link:http://www.java.net/blogs/driscoll/[+Джим Дрисколл (Jim Driscoll)+]
