Статьи

Управляемый событиями MVC с JSF и JBoss Seam — распространенные ошибки

Большинство веб-фреймворков Java были разработаны с учетом MVC; однако JSF, вероятно, является одним из немногих, кто достиг цели. Комбинируя JSF с JBoss Seam и Facelets, разработчик может реализовать шаблон проектирования MVC, используя:

  • Бобы JBoss Seam POJO, представляющие модель данных
  • Компоненты JBoss Seam, представляющие контроллер, где реализована бизнес-логика и где реализован уровень доступа к данным
  • XHTML Facelets, представляющие вид

Это представляет собой истинную реализацию MVC, потому что bean-компонент JBoss Seam POJO действует как DTO, позволяя читать / записывать данные. Компонент действия JBoss Seam используется для манипулирования объектом данных, а фасеты XHTML отображают только те данные, которые «проталкиваются» в компоненты Seam.

Тем не менее, хотя теории, лежащие в основе MVC и модели JSF / Seam / Facelets, могут показаться очевидными, я видел, как разработчики часто злоупотребляют ими. Вот несколько распространенных ошибок, с которыми я столкнулся:

Сценарий 1 — Размещение кода инициализации контроллера в фасетах:

<s:div rendered="#{bean.init()}">
<h:outputText value="#{bean.text}"/>
</s:div>

 

Сценарий 2. Размещение методов поиска данных в фасетах:

<s:div>
<h:panelGroup rendered="#{bean.getAccountbyAccountNumber(accountNumber)}">
<h:outputText value="#{accountBean.firstname}"/>
<h:outputText value="#{accountBean.lastname}"/>
</h:panelGroup>
</s:div>

 

Сценарий 3 — Неправильное понимание жизненных циклов JSF и области применения JBoss Seam:

<s:div id="renderSection" rendered="#{bean.isVisible()}">
<h:outputText value="#{bean.text}"/>
<a4j:commandLink action="#{actionBean.retrieveBean()}" reRender="renderSection" />
</s:div>

… где бин был инициализирован через некоторые другие события, и у бина есть «Область действия».

ПРИМЕЧАНИЕ: указанная выше ссылка никогда не может быть «нажата», поскольку на этапе «восстановления представления» «renderSection» никогда не отображается.

 

6 жизненных циклов JSF

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

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

(источник: учебное пособие по JEE )

  1. Восстановить вид
  2. Применить значения запроса; обрабатывать события
  3. Проверки процесса; обрабатывать события
  4. Обновить значения модели; обрабатывать события
  5. Вызвать приложение; обрабатывать события
  6. Предоставить ответ

На мой взгляд, восстановление представления — самая сложная фаза для понимания. На этапе восстановления представления это может быть новое представление или создаваемый постбэк:

  • Новый вид создается и сохраняется в FaceContext, когда вы посещаете страницу в первый раз
  • Обратная передача — это когда пользователь отправляет форму на существующую визуализированную страницу.

В сценарии 3, когда обработчик представления восстанавливает представление из FaceContext, ему будет не хватать значения bean-объекта Event Scope и, следовательно, остановлено выполнение.

 

Управляя всем от событий

В зависимости от того, насколько сложна логика при отображении страницы, вы можете решить, следует ли использовать шаблон, описанный ниже. Давайте посмотрим на пример макета ниже

Это простая веб-страница почтового ящика, и обратите внимание, что всякий раз, когда вы выбираете вкладку слева: входящие, исходящие, контакты … и т. Д., Или выбираете другую учетную запись из раскрывающегося списка учетных записей, дерева папок, списка писем и содержимого просмотров почты должны быть обновлены. Очевидно, мы могли бы реализовать это, имея

<h:selectOneMenu id="account" value="#{accountBean.selectedAccount}">
<f:selectItem itemValue="Select an account...."/>
<f:selectItems value="#{accountBean.validAccounts}"/>
<a4j:support event="onchange" actionListener="#{accountSelectAction.selectOneAccount}"
reRender="mailPanel" ajaxSingle="true"/>
</h:selectOneMenu>

 

… и в методе selectOneAccount реализуется следующая логика:

  1. Получить список папок
  2. Установить папки по умолчанию
  3. Получить список писем в папке
  4. Установите отображение почты по умолчанию
  5. Получить содержимое почты

Гораздо более элегантное решение заключается в реализации:

Event.raiseEvent("ReloadFoldersEvent");Event.raiseEvent("ReloadFoldersEvent");

 

…. и прослушиватель метода RetrieveFolders для прослушивания ReloadFoldersEvent . Как только поиск в папке будет завершен, мы хотим вызвать другое событие в методе, чтобы вызвать получение почты:

Event.raiseEvent("ReloadMailsEvent");

 

Повторите этот шаблон для метода RetrieveMails (ReloadMailContentsEvent) и метода RetrieveMailContent .

Повышая значения параметров ReloadFoldersEvent, ReloadMailsEvent, ReloadMailContentsEvent и прослушивая события в контроллерах Seam, можно избежать многократного создания очень похожей логики в методах контроллера RetrieveFolders, RetrieveMails и RetrieveMailContents .

Более того, правильный MVC достигается за счет того, что методы RetrieveFolders, RetrieveMails и RetrieveMailContents (Controller) могут заполнять фасоли значений (Model) в событиях, а facelets (View) требуется ТОЛЬКО для взаимодействия с фасолями значений для заполнения пользовательского интерфейса.

От Коле Enterprise Consulting блог

#{bean.init()}