Я создаю веб-приложение для генерации отчетов из нескольких источников данных.Каждый источник данных имеет свой собственный набор столбцов, которые можно настроить в списке выбора Primefaces.Когда источник переключен, содержимое списка выбора должно быть обновлено, и выбранные столбцы из предыдущего источника должны быть кэшированы.
reports-edit.xhtml
<p:selectOneMenu id="select_source"
value="#{reportingEditView.uiReporting.source}"
converter="omnifaces.SelectItemsConverter"
required="true"
requiredMessage="Source selection may not be empty.">
<f:selectItem itemLabel="Select One"
itemValue="#{null}"
itemDisabled="true"/>
<f:selectItems
value="#{reportingEditView.uiReporting.channel.sources}"
var="source"
itemLabel="#{source.name}"/>
<p:ajax listener="#{reportingEditView.onSourceChange}"
update="picklist_columns"/>
</p:selectOneMenu>
<p:pickList id="picklist_columns"
value="#{reportingEditView.uiReporting.columnModel}"
var="col"
itemValue="#{col}"
itemLabel="#{col.column.displayName}"
showSourceFilter="true"
filterMatchMode="contains"
responsive="true"
validator="pickListTargetNotEmptyValidator"
immediate="true">
<f:facet name="targetCaption">Spalten</f:facet>
<o:converter converterId="omnifaces.ListConverter"
list="#{reportingEditView.uiReporting.allAvailableColumns}"/>
<p:ajax event="transfer"
listener="#{reportingEditView.onPicklistTransfer}"
update="@this"/>
</p:pickList>
<p:commandButton id="button_save"
value="Speichern"
action="#{reportingView.save}"
icon="fa fa-fw fa-save"
update="panel_edit_report"
validateClient="true">
</p:commandButton>
ReportingEditView.java
@ManagedBean
@SessionScope
@Slf4j
public class ReportingEditView implements Serializable
{
public void onSourceChange()
{
// get all available columns used by converter for new source selection.
List<RepColumn> availableColumns =
this.columnUtils.convertToRepColumn(this.uiReporting.getSource().getAvailableColumns());
availableColumns.sort(new RepColumnAlphabeticalComparator());
Source source = this.uiReporting.getSource();
Source sourceCache = this.uiReporting.getSourceCache();
if(!(this.uiReporting.getColumnModelCache().containsKey(source)))
{
this.uiReporting.getColumnModelCache().put(source, new DualListModel<>(availableColumns, new ArrayList<>()));
}
// cache columns for previous selected source
this.uiReporting.getColumnModelCache().put(sourceCache, this.uiReporting.getColumnModel());
// set columns for new source selection
this.uiReporting.setColumnModel(this.uiReporting.getColumnModelCache().get(source));
// set source cache for next change
this.uiReporting.setSourceCache(source);
this.uiReporting.setAllAvailableColumns(availableColumns);
}
public void onPicklistTransfer(TransferEvent event)
{
if(event.isRemove())
{
// order source columnModel alphabetically if a column is removed from reporting and therefore appears back in source column list
List<RepColumn> orderedColumns = this.uiReporting.getColumnModelCache().get(this.uiReporting.getSource()).getSource();
orderedColumns.sort(new RepColumnAlphabeticalComparator());
this.uiReporting.getColumnModel().setSource(orderedColumns);
}
}
}
PickListTargetNotEmptyValidator.java
@FacesValidator("pickListTargetNotEmptyValidator")
public class PickListTargetNotEmptyValidator implements Validator
{
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
{
if(CollectionUtils.isEmpty(((DualListModel) value).getTarget()))
{
((UIInput) component).setValid(false);
Messages.addError(component.getClientId(context), "Column List may not be empty.", this);
}
}
}
Выбор столбцов, переключение между источниками и кэширование работает нормально, а значения устанавливаются так, как это должно быть при отладке.Если я первоначально выберу источник и несколько столбцов, я могу отправить форму, и отчет будет сохранен.Даже переключение с одного источника на другой и выбор некоторых столбцов работает.Но когда я теперь переключаюсь обратно на первый источник и подтверждаю, проверка завершается неудачно, потому что DualListModel, переданный в валидатор, полностью пуст.
Я использую Java 8 и Primefaces 6.2.
Что можетбыть причиной такого поведения и каковы возможные решения?