Вид:
<h:form ...
<p:dataTable value="#{myBean.list}" var="data" ...
<p:column ...
<h:commandButton action="#{controller.method(data.id)}" />
</p:column>
</p:dataTable>
</h:form>
Контроллер:
@ApplicationScoped
public class Controller {
public String method(final Long dataId) {
/* Do business */
return URL_WITH_REDIRECT;
}
}
Производитель
(с использованием аннотации @ViewScoped
CDI, как описано здесь)
@ApplicationScoped
public class Producer {
@Named @ViewScoped @Producer
public MyBean getMyBean() {
final MyBean bean = new MyBean();
bean.list = new ArrayList<Data>(); // where Data has a Long id field
/* Do business and populate list */
return bean;
}
}
Проблема и ее сценарий
GET
the page- The bean is produced
- Представление визуализируется
- Ответ отправлен в браузер
- Click the button
- Data is
POST
ed to server - Этапы 1– 4 выполняются без каких-либо проблем и используют
@ViewScoped
bean-компоненты, как и ожидалось. - Фаза 5:
controller.method
вызывается сdata.id
и обращается к bean-компонентам, сгенерированным в 1.1. - Метод возвращает перенаправление
String
- <сильный>!! Продюсер вызывается снова!! — мы все еще находимся в фазе APPLICATION_INVOCATION, но уже после фактического вызова метода
- Data is
- Браузер получает перенаправление
GET
следующая страница...
Полуослиное решение, которое работает:
Короче говоря: при щелчке скопируйте идентификатор за пределы таблицы данных и нажмите кнопку отправки.
На h:commandButton
внутри столбца таблицы добавлено:
onclick="$('input[id*=selectedDataId]').val('#{data.id}'); $('button[id*=callMethod]').trigger('click');"
Вне стола:
<h:inputHidden id="{selectedDataId}"binding="#{selectedDataId}"/>
<p:commandButton type="submit"
id="callMethod"
label="Hidden button"
action="#{controller.method(selectedDataId.value)}"/>
В конце концов это работает, но я не смог понять, что заставляет первый и базовый подход повторно инициализировать компонент с областью видимости. Глядя на трассировку стека (см. ниже), кажется, что он перестраивает строки.
Вопрос:
Есть ли у кого-нибудь объяснение и, возможно, предостережения, на которые следует обратить внимание в отношении этой проблемы?
Трассировки стека
Где: getPipelinecheckSearchResults
— это вызов для получения списка, поддерживающего таблицу, что приводит к вызову производителя.
Что я уже просмотрела:
Я прочитал следующие статьи/вопросы SO, не получив лучшего понимания того, почему вышеуказанное (1-е) решение работает именно так.
Компонент ViewScoped воссоздается каждый раз, когда я нажимаю commandButton в моей таблице данных
Как я могу передать выбранную строку в commandLink внутри dataTable?
http://balusc.blogspot.de/2010/06/benefits-and-pitfalls-of-viewscoped.html
myBean
. Та же проблема. (Хотя я бы не стал вкладывать логику в модели, так как они должны быть тупыми). 2. Да, читал, но это относится кactionListener
, а в моем случае re@Produc
tion после APPLICATION_INVOCATION, поэтомуaction
правильно находит путь - person Matyas   schedule 28.05.2013