Технологии рендеринга страниц

Реализация JSF Mojarra позволяет создавать страницы с помощью технологии Facelets или JSP. Facelets – это страницы в формате XHTML, в то время как JSP – они и в Африке JSP. Sun (Oracle) рекомендует использовать Facelets (страницы xhtml) так как они быстрее рендерятся движком JSF, что значительно сказывается на быстродействии всего web-приложения а также поддерживают технологию шаблонов “из коробки”.

Комфортная разработка

В JSF 2 адаптировали одну из идей Ruby On Rails. Существует настройка, которая определяет режим работы приложения: режим разработки, режим тестирования и продакшн режим. В режиме разработки, программист получает подробный вывод об исключительной ситуации на JSF-страницу. Помимо стэк-трэйса выводится дерево компонентов и список Scoped Variables (переменных с областью действия scope).

Выглядит это так (щелкните чтобы увеличить):

Исключительная ситуация в JSF 2 в режиме Development

Исключительная ситуация в JSF 2 в режиме Development

Здесь я пытаюсь взять из ресурсного бандла ресурс hello.worl, который не существует. По умолчанию JSF 2 работает в режиме Production. Режим Development включается с помощью контекстного параметра в web.xml:

    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

Поддержка Groovy

Mojarra поддерживает Groovy для реализации управляемых бинов и компонентов. Groovy – это динамический язык. Благодаря Groovy можно значительно увеличить скорость разработки. Как это сделать читатйте в статье “Groovy на практике: сокращение кода с помощью Groovy” на сайте IBM.

Поддержка Ajax

JSF 2 предоставляет ряд функций для поддержки Ajax. Одна из особенностей – так называемая частичная визуализация (partial rendering). Вместо обновления всей страницы, рендерится только необходимая часть, которая затем вставляется в текущую страницу. Обычный updater из JQuery, но уже встроенный в фреймворк и настроенный на работу с ним.

Для работы с Ajax в JSF 2 введен новый тэг

<f:ajax>

который добавляет функциональность Ajax в существующие компоненты. В следующем блоке кода в качестве примера приводится Ajax-кнопка при щелчке на которой JSF отправляет Ajax-запрос слушателю действий actionListener, методу increase из класса AjaxBean, который в свою очередь изменяет значение счетчика, в результате чего, значение в компоненте outputText изменяется на новое.

<h:form id="formId">
  The counter value is <h:outputText value="#{ajaxBean.counter}" id="counter"/>
  <h:commandButton actionListener="#{ajaxBean.increase}" value="Ajax call">
    <f:ajax render="counter"  />
  </h:commandButton>
</h:form>

Замечание: если изменяемый компонент и компонент, отправляющий Ajax-запрос, находятся на разных уровнях вложенности, то необходимо указать полный путь до изменяемого компонента. Например:

...
<f:ajax render=":foo:counter"/>
...
<h:form id="foo">
    <h:outputText value="#{ajaxBean.counter}" id="counter"/>
</h:form>

Если отключить JavaScript в браузере, то компоненты будут вести себя как обычные (не Ajax), т.е., например, кнопка будет выполнять обычную отправку формы на сервер.

Еще один интересный атрибут тэга f:ajax – execute. Он посылает Ajax-запрос и обрабатывает жизненный цикл только указанных компонентов. Следующий код выполнит все проверки и перерендерит тэг h:messages чтобы отобразить ошибки.

<h:inputText id="age" value="#{ajaxValidation.age}" required="true">
    <f:validateDoubleRange minimum="5" maximum="99"/>
    <f:ajax execute="age" event="blur" render="age-error"/>
</h:inputText>
 
<h:messages id="age-error" for="age"/>

Обработка CSS и JavaScript

В JSF ресурсами может быть все что угодно, например скрипты JavaScript, таблицы стилей CSS, картинки и т.д. Следующий тэг добавляет test.js в head страницы независимо от того, где он объевлен.

<h:outputScript library=“js” name=“test.js” target=“head”/>

Ресурсы нужно хранить в каталоге resources в корне web-приложения или в META-INF/resources, который находится в classpath приложения. Однако, лучше группировать ресурсы в библиотеки. Библиотека в терминах JSF 2 – это подкаталог в каталоге resources. Вот пример структуры каталогов:

webroot/resources/css/default.css
webroot/resources/images/foo.gif
webroot/resources/images/bar.gif
webroot/resources/js/myscript.js

К библиотеке можно добавить версии и локали. Это очень гибкий подход для обработки различных версий и регионально зависимых ресурсов. Например:

webroot/resources/de/js/default.js/1.0.js
webroot/resources/de/js/default.js/1.1.js
webroot/resources/en/js/default.js/1.0.js

Пользователи с локалью (de) будут использовать следующий тэг, который будет отдавать последню версию немецкого скрипта default.js.

<h:outputScript library="js" name="default.js" />

Также можно указать версию ресурса:

<h:outputScript library="js" resourceVersion="1.0" name="default.js" />

Безопасность

Реализация JSF Mojarra не предоставляет каких-либо серьезных средств безопасности, но легко интегрируется с Spring Security, а при использовании JSF с JBoss Seam, можно использовать его (Seam) функции обеспечения безопасности. Оба подхода позволяют защищать страницы и методы, а Spring даже предоставляет поддержку обеспечения безопасности домена (доменной модели). Это значит что можно проверить, имеет ли пользователь права на объект, возвращаемый каким-либо методом. Информация о правах доступа хранится в очень простой форме. Каждый объект должен иметь уникальный идентификатор(id), а класс, id объекта, и id пользователя и его прав доступа (чтение, запись, удаление и т.д.) хранятся в базе данных. Метод-перехватчик проверяет возвращаемые другим методом объекты и принимает соответствующие решения.

Такой подход к обеспечнию безопасности может быть избыточным для некоторых приложений, поэтому есть более простой способ, предоставляемый средствами JSF Mojarra. Этот способ описан в статье “Improving JSF Security Configuration With Secured Managed Beans“. В описанном в этой статье способе используются глобальные слушатели действий и пользовательские обработчики навигации. Глобальный слушатель вызывается до выполнения вызываемого метода. Он проверяет, имеет ли пользователь необходимые права (роли) для доступа к методу. Необходимые роли могут быть определены при помощи аннотаций к методу. Например:

@SecurityRoles("customer-admin-adv, root")
public String delete() {
  System.out.println("I'm a protected method!");
  return "delete-customer";
}

Этот подход хорош тем, что очень прост, но в тоже время отлично делает свое дело.

Достоинста JSF

  1. Много поставщиков решений (Oracle, IBM, JBoss и т.д.), реализующих в своих продуктах поддержку JSF, поэтому можно ожидать хороший уровень поддержки и качества компонентов.
  2. JSF позволяет создавать повторно используемые компоненты, что способствует повышению производительности.
  3. Много готовых к использованию компонентов от серьезных разработчиков: Apache, Richfaces, Infragistics, Oracle, и т.д.
  4. Хорошо продуманная концепция слушателей действий.
  5. Отличная реализация концепций валидаторов и конверторов. В отличие от Struts, JSF хранит логику валидации в непосредственной близости от описания компонента.
  6. Внедряемый в компоненты JavaScript код и отличная поддержка Ajax.

Недостатки JSF

С недостатками JSF я пока плохо знаком, читал лишь только что есть какие-то сложности с логированием JSF-web-приложений.

В Internet много статей типа “Advantages and Disadvantages JSF”, однако практически все они о ранних версиях JSF. В версии 2.0 все недостатки, описывемые в этих статьях исправлены. А в остальном, видимо народ еще не достаточно разобрался с JSF 2.

В этой статье мы рассмотрели несколько положительных особенностей JSF Mojarra, но толком не рассмотрели ни одного недостатка. Надеюсь исправить это упущение в следующих постах.