Статьи

Как работает JSF и как его отлаживать — является ли полиглот альтернативой?

JSF — это не то, что мы часто думаем. Это также фреймворк, который может быть несколько сложным для отладки, особенно при первом обнаружении. В этом посте давайте рассмотрим, почему это так, и предоставим некоторые методы отладки JSF. Мы рассмотрим следующие темы:

  • JSF это не то, что мы часто думаем
  • Трудности отладки JSF
  • Как систематически отлаживать JSF
  • Как работает JSF — жизненный цикл JSF
  • Отладка Ajax-запроса от браузера к серверу и обратно
  • Отладка Javascript-кода JSF-интерфейса
  • Заключительные мысли — альтернативы? (вопросы к читателю)

JSF это не то, что мы часто думаем

JSF на первый взгляд выглядит как корпоративная оболочка Java / XML, но на самом деле это не так . Это на самом деле фреймворк Java / Javascript с полиглотом, где клиентская часть Javascript является неотъемлемой частью и также важна для ее понимания. Он также имеет хорошую поддержку для прямого использования HTML / CSS.

Разработчики JSF уже являются разработчиками полиглотов, основным языком которых является Java, но все еще необходимо использовать Javascript.

Трудности отладки JSF

Сравнивая JSF с GWT и AngularJS в предыдущем посте, я обнаружил, что (наиболее часто используемый) подход, который использует фреймворк для абстрагирования HTML и CSS от разработчика, стоящего за XML, усложняет отладку, поскольку создает дополнительный уровень Косвенная.

Также возможен более прямой подход к использованию HTML / CSS напрямую, но кажется, что разработчики корпоративных Java в большинстве случаев склонны придерживаться XML, потому что это более знакомая технология. Также другая проблема заключается в том, что часть Javascript на стороне клиента инфраструктуры / библиотек не очень хорошо документирована, и часто важно понимать, что происходит.

Единственный способ систематической отладки JSF

Когда я впервые столкнулся с JSF, я сначала попытался приблизиться к нему только из Java, XML и документации. Хотя я мог выполнять часть работы таким образом, там, где часто возникали ситуации, когда такого подхода было недостаточно.

Я пришел к выводу, что для эффективной отладки приложений JSF необходимо понимание следующего:

  • HTML
  • CSS
  • Javascript
  • HTTP
  • Chrome Dev Tools, Firebug или эквивалентный
  • Жизненный цикл JSF

Это может показаться удивительным для разработчиков, которые работают в основном на Java / XML, но этот веб-ориентированный подход к отладке JSF — единственный способ, с помощью которого мне удалось решить многие требования, которые требовали некоторой значительной настройки компонентов или чтобы исправить некоторые ошибки.

Давайте начнем с понимания внутренней работы JSF, чтобы лучше ее отладить.

JSF взять на себя MVC

Подход JSF к MVC заключается в том, что все 3 компонента находятся на стороне сервера:

  • Модель — это дерево простых объектов Java
  • Представление — это шаблон на стороне сервера, определенный в XML, который читается для построения определения представления в памяти
  • Контроллер — это сервлет Java, который получает каждый запрос и обрабатывает их через серию шагов

Предполагается, что браузер является просто механизмом рендеринга для HTML, генерируемого на стороне сервера. Ajax достигается путем отправки частей страницы для обработки сервером и запроса к серверу «перекрашивать» только части экрана, не отходя от страницы.

Жизненный цикл JSF

Как только HTTP-запрос достигает сервера, он перехватывается контроллером JSF, который затем обрабатывает его. Запрос проходит через несколько этапов, известных как жизненный цикл JSF, который необходим для понимания работы JSF:

jsfIntro-жизненный цикл

Цели дизайна жизненного цикла JSF

Весь смысл жизненного цикла заключается в 100% управлении MVC на стороне сервера, используя браузер только в качестве платформы рендеринга.

Первоначальная идея заключалась в том, чтобы отделить платформу рендеринга от модели компонентов пользовательского интерфейса на стороне сервера, чтобы позволить заменить HTML альтернативными языками разметки, поменяв фазу отклика рендеринга.

Это было в начале 2000-х годов, когда HTML можно было вскоре заменить альтернативами на основе XML (которых никогда не было), а затем появился HTML5. Кроме того, браузеры стали гораздо более популярными, чем в наши дни, и идея кросс-браузерных библиотек Javascript не получила широкого распространения.

Итак, давайте пройдемся по каждой фазе и посмотрим, как отладить ее, если это необходимо, начиная с браузера. Давайте базируемся на простом примере, который использует Ajax-запрос.

Пример JSF 2 Hello World

Ниже приведена минимальная страница JSF 2, которая получает входной текст от пользователя, отправляет текст через Ajax-запрос в бэкэнд и обновляет только выходную метку:

01
02
03
04
05
06
07
08
09
10
<h:body
    <h3>JSF 2.2 Hello World Example</h3>
    <h:form>
        <h:outputtext id="output" value="#{simpleFormBean.inputText}"></h:outputtext
        <h:inputtext id="input" value="#{simpleFormBean.inputText}"></h:inputtext>
        <h:commandbutton value="Submit" action="index">
            <f:ajax execute="input" render="output">
        </f:ajax></h:commandbutton>
    </h:form>
</h:body

Страница выглядит так:

Привет мир

После одного Ajax-запроса — на сервер и обратно

Давайте нажмем кнопку «Отправить», чтобы активировать Ajax-запрос, и перейдем на вкладку «Chrome Dev Tools Network» (щелкните правой кнопкой мыши и осмотрите любой элемент на странице). Что происходит по сети? Вот что мы видим в разделе данных формы запроса:

1
2
3
4
5
6
7
8
j_idt8:input: Hello World  
javax.faces.ViewState: -2798727343674530263:954565149304692491  
javax.faces.source: j_idt8:j_idt9
javax.faces.partial.event: click
javax.faces.partial.execute: j_idt8:j_idt9 j_idt8:input
javax.faces.partial.render: j_idt8:output
javax.faces.behavior.event: action
javax.faces.partial.ajax:true

Этот запрос говорит:

Новое значение поля ввода — «Hello World», пришлите мне новое значение только для поля вывода и не уходите с этой страницы.

Посмотрим, как это можно прочитать из запроса. Как мы видим, новые значения формы отправляются на сервер, а именно значение «Hello World». Это значение нескольких записей:

  • javax.faces.ViewState идентифицирует представление, из которого был сделан запрос.
  • Запрос является Ajax-запросом, как указано флагом javax.faces.partial.ajax ,
  • Запрос был вызван щелчком, как определено в javax.faces.partial.event .

Но что это за строки? Это сгенерированные пробелами идентификаторы элементов HTML. Например, вот как мы можем увидеть, какой элемент страницы соответствует j_idt8:input , используя Chrome Dev Tools:

img2_component_ids

Есть также 3 дополнительных параметра формы, которые используют эти идентификаторы, которые связаны с компонентами пользовательского интерфейса:

  • javax.faces.source : идентификатор элемента HTML, который javax.faces.source этот запрос, в данном случае идентификатор кнопки отправки.
  • javax.faces.execute : список идентификаторов элементов, значения которых отправляются на сервер для обработки, в данном случае это поле ввода текста.
  • javax.faces.render : список идентификаторов разделов страницы, которые должны быть «перекрашены», в данном случае только для поля вывода.

Но что происходит, когда запрос попадает на сервер?

Жизненный цикл JSF — фаза восстановления

Как только запрос достигает сервера, контроллер JSF проверит
javax.faces.ViewState и определить, к какому виду он относится. Затем он создаст или восстановит представление представления в Java, которое как-то похоже на определение документа на стороне браузера.

Представление будет прикреплено к запросу и использовано повсеместно. Обычно нет необходимости отлаживать этот этап во время разработки приложения.

Жизненный цикл JSF — применить значения запроса

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

Этот метод извлекает отправленное значение для рассматриваемого виджета из запроса HTTP и сохраняет его в самом виджете.

Чтобы отладить это, давайте поместим HtmlInputText останова в метод HtmlInputText класса HtmlInputText , чтобы увидеть значение «Hello World»:

img4_debug_ARV

Обратите внимание на условную clientId останова, используя HTML clientId нам поля. Это позволит быстро отлаживать только декодирование нужного нам компонента, даже на большой странице со многими другими подобными виджетами. Следующим после декодирования является этап проверки.

Жизненный цикл JSF — проверки процессов

На этом этапе применяются проверки, и если установлено, что значение содержит ошибку (например, дата недействительна), то запрос обходит приложение Invoke и переходит непосредственно к фазе ответа ответа.

Для отладки этого этапа аналогичную processValidators останова можно поставить для метода processValidators или в самих валидаторах, если вы знаете, какие из них или они являются пользовательскими.

JSF Lifecycle — Обновление модели

На этом этапе мы знаем все представленные значения, где они верны. JSF теперь может обновить модель представления, применяя новые значения, полученные в запросах, к простым объектам Java в модели представления.

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

JSF Lifecycle — Приложение Invoke

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

Здесь выполняются прослушиватели действий, определенные в определении представления XML (свойства ‘action’ и теги слушателей).

Жизненный цикл JSF — ответ Render

На этом этапе я больше всего отлаживаюсь: почему значение не отображается так, как мы ожидаем, и т. Д., Все это можно найти здесь. На этом этапе представление и новые значения модели будут преобразованы из объектов Java в HTML, CSS и, в конечном итоге, в Javascript и отправлены обратно по проводам в браузер.

Эта фаза может быть отлажена с использованием точек останова в encodeBegin , encodeChildren и encodeEnd рассматриваемого компонента.

Компоненты будут либо визуализироваться, либо делегировать рендеринг классу Renderer .

Вернуться в браузер

Это была долгая поездка, но мы вернулись туда, откуда начали! Вот как выглядит ответ, сгенерированный JSF после получения в браузере:

1
2
3
4
5
6
7
<!--?xml version='1.0' encoding='UTF-8'?-->
<partial-response
    <changes>
        <update id="j_idt8:output"><span id="j_idt8:output"></span></update>
        <update id="javax.faces.ViewState">-8188482707773604502:6956126859616189525></update>
    </changes>
</partial-response

То, что будет делать Javascript-часть фреймворка, — это принимать содержимое частичного ответа, обновляя за обновлением.

Используя идентификатор обновления, обратный вызов JSF на стороне клиента будет искать компонент с этим идентификатором, удалять его из документа и заменять его новой обновленной версией.

В этом случае «Hello World» будет отображаться на ярлыке рядом с полем ввода текста!

И вот как JSF работает под капотом. Но что если нам нужно отладить часть фреймворка Javascript?

Отладка кода JSF Javascript

Инструменты Chrome Dev могут помочь в отладке клиентской части. Например, допустим, что мы хотим остановить клиента при запуске Ajax-запроса. Нам нужно перейти на вкладку источников, добавить точку останова XHR (Ajax) и запустить действие браузера. Отладчик остановится и стек вызовов может быть проверен:

debug_frontend

Для некоторых сред, таких как Primefaces, источники Javascript могут быть минимизированы (не читаемыми человеком), потому что они оптимизированы по размеру.

Чтобы решить эту проблему, загрузите исходный код библиотеки и выполните минимизированную сборку jar. Обычно есть инструкции для этого, в противном случае проверьте проект poms. Это установит в ваш репозиторий Maven jar с не минифицированными источниками для отладки.

Тег отладки пользовательского интерфейса:

Тег ui:debug позволяет просматривать много информации об отладке с помощью сочетания клавиш, подробности см. Здесь .

Последние мысли

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

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

Является ли полиглот альтернативой?

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

Вполне возможно, что подход, основанный на полиглоте бэкэнда Java плюс внешний интерфейс только для Javascript, может оказаться эффективным в ближайшем будущем, особенно с использованием некоторой клиентской инфраструктуры MVC, такой как Angular .

Это потребует изучения Javascript (посмотрите на статью Javascript для разработчиков Java, если вам интересно), но в любом случае это уже часто необходимо для разработки пользовательских виджетов в JSF.

Выводы и некоторые вопросы, если у вас есть время

Спасибо за чтение, пожалуйста, уделите время, чтобы поделиться своими мыслями по этим вопросам в комментариях ниже:

  • Считаете ли вы, что разработка полиглотов (Java / Javascript) является жизнеспособной альтернативой в целом и на вашем рабочем месте в частности?
  • Нашли ли вы одну из основанных на GWT платформ (обычные GWT, Vaadin, Errai) или Play Framework более простыми в использовании и более производительными?