@PostConstruct вызывается несколько раз для bean-компонента @ConversationScoped - PullRequest
3 голосов
/ 28 мая 2011

У меня есть bean-компонент @ConversationScoped с методом запуска, например:

@PostConstruct
public void start() {
    if (conversation.isTransient()) {
        conversation.begin();
        log.debug("conversation.getId(): " + conversation.getId());
    }
}

Моя проблема заключается в том, что при каждом обновлении страницы запускается новый диалог, новый диалог также запускается каждый раз, когда у меня есть вызов AJAX для метода в компоненте (что является моей основной проблемой).

То, что я действительно хочу, это чтобы разговор с Сэмом зависал до тех пор, пока я не вызову вручную файл dialog.end (). Что мне здесь не хватает?

Ответы [ 6 ]

5 голосов
/ 30 мая 2011

Немного не по теме, но, надеюсь, ценно:

Я не уверен на 100%, что @PostConstruct - подходящее место для начала разговора.Я бы предпочел использовать Face-событие вроде этого:

<f:metadata>
        <f:event type="javax.faces.event.PreRenderViewEvent"
                listener="#{myBean.init}" />
</f:metadata>

и начать разговор, если вы уверены, что не находитесь в запросе обратной передачи JSF.

public void init() {
       if (!FacesContext.getCurrentInstance().isPostback() && conversation.isTransient()) {
          conversation.begin();
       }
    }

Есливы используете шов 3, это еще проще:

<f:metadata>
   <s:viewAction action="#{myBean.init}" if="#{conversation.transient}" />
</f:metadata>
3 голосов
/ 25 июня 2011

Концепция встроенного в JSR-299 Conversation немного нарушена.По крайней мере, для приложений JSF.Использование @PreRenderViewEvent в основном отбросило бы все преимущества этого подхода, так как он давал бы каждый @ConversationScoped bean longRunning.

Вместо этого вы можете попробовать использовать Apache MyFaces CODI @ConversationScoped.CODI - это библиотека расширений CDI, которая хорошо работает как с Apache OpenWebBeans, так и с Weld.Кроме того, он также предоставляет контексты @ViewScoped, @ViewAccessScoped (тип автоматического разговора) и @WindowScoped.

Подробнее: https://cwiki.apache.org/confluence/display/EXTCDI/Index

3 голосов
/ 29 мая 2011

Проверяли ли вы, что вызовы (AJAX) содержат параметр идентификатора разговора (cid)?

Если этого не произойдет, ожидается, что новый разговор начнется для каждого звонка.

2 голосов
/ 30 мая 2011

Это все в документах:

Область разговора активна:

во время всех стандартных этапов жизненного цикла любого запроса JSF о лицах или не лицах.

Контекст диалога обеспечивает доступ к состоянию, связанному с конкретным диалогом. С каждым запросом JSF связан диалог. Эта ассоциация автоматически управляется контейнером в соответствии со следующими правилами:

Любой запрос JSF имеет ровно один связанный разговор. Диалог, связанный с запросом JSF, определяется в начале фазы просмотра восстановления и не изменяется во время запроса.

Любой разговор находится в одном из двух состояний: временное или длительное.

По умолчанию разговор временный Временный диалог может быть помечен как длительный, вызвав Conversation.begin () Длительный разговор может быть помечен как временный, вызвав Conversation.end ()

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

Если диалог, связанный с текущим запросом JSF, находится в переходном состоянии в конце запроса JSF, он уничтожается и контекст диалога также уничтожается.

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

Контекст продолжительного диалога, связанный с запросом, который отображает представление JSF, автоматически распространяется на любой запрос лиц (отправка формы JSF), который исходит от этой отображаемой страницы. Длительный контекст диалога, связанный с запросом, результатом которого является перенаправление JSF (перенаправление, полученное в результате правила навигации или JSF NavigationHandler), автоматически передается в результирующий запрос не для лиц и в любой другой последующий запрос на тот же URL-адрес. Это достигается с помощью параметра запроса GET с именем cid, содержащего уникальный идентификатор диалога. Длительный диалог, связанный с запросом, может распространяться на любой запрос, не связанный с лицами, посредством использования параметра запроса GET с именем cid, содержащего уникальный идентификатор диалога. В этом случае приложение должно управлять этим параметром запроса.

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

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

Автор: Гэвин Кинг, Пит Мьюир

0 голосов
/ 23 июня 2013

Как ни странно, если вы добавляете прослушиватель событий в ваш Facelet, даже если он вызывает пустой метод, действие формы сгенерированного источника будет иметь параметр 'cid' и, следовательно, вызов AJAX не создаст новый диалог , Без прослушивателя событий в cid отсутствует действие в форме.

<f:metadata>
    <f:event listener="#{myBean.dummy}" type="preRenderView" />
</f:metadata>

MyBean.java

public void dummy() {}
0 голосов
/ 19 августа 2011

ИМХО Разговоры CDI нарушены по замыслу, и Стерберг указал на многообещающую альтернативу. В моем приложении у меня та же проблема, и в настоящее время я рефакторинг его в CDI + CODI 1, и он просто чувствует себя хорошо. @ConversationScoped решает все эти проблемы. При рефакторинге моего приложения я мог решить множество неприятных случаев с помощью @ViewAccessScoped. Спасибо, Струберг, за то, что указал нам на это!

...