Сохранение настроек портлета Liferay 7 с использованием JSF selectOneListbox

Я обновляю портлет JSF, который был у нас в Liferay 6.2, до Liferay 7.

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

<h:selectOneListbox id="listModeSelector" value="#{user.listMode}" size="1">
    <f:selectItems value="#{user.listModes}" var="mode"
        itemLabel="#{mode.label}" itemValue="#{mode.value}" />
    <f:ajax event="change" execute="@this" render=":metricsPanel" />
</h:selectOneListbox>

когда user.setListMode вызывается после изменения selectOneListboxпортлет сохранит новую опцию в настройках портлета с вызовом к PortletPreferences компонента setValue а также store функции:

@ManagedBean
@SessionScoped
public class User {
    private static final String LIST_MODE_KEY = "listMode";
    private ListMode listMode;
    private PortletPreferences preferences;

    public User() {
        PortletRequest request = ((PortletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest());
        preferences = request.getPreferences();
        listMode = ListMode.fromValue( preferences.getValue( LIST_MODE_KEY, ListMode.Normal.getValue() ) );
    }

    public String getListMode() {
        return listMode.getValue();
    }

    public ListMode[] getListModes() {
        return ListMode.values();
    }

    public void setListMode( String listModeValue ) {
        this.listMode = ListMode.fromValue( listModeValue );
        try { 
            preferences.setValue( LIST_MODE_KEY, listModeValue );
            preferences.store();
        }
        catch ( ...Exception e ) {
            log.error( "unable to persist listMode: " + e.getMessage(), e );
        }

    }

}

Когда они меняют эту настройку, мы хотим, чтобы она оставалась неизменной для них, для любых будущих сессий. Но после перехода на Liferay 7 это вызывает IllegalStateException с сообщением Preferences cannot be stored inside a render call,

Итак, мой вопрос: в Liferay 7 JSF, есть ли способ хранить PortletPreferences от изменения до предмета вроде selectOneListboxвместо отправки формы? Если нет, каков будет правильный способ сделать это?

1 ответ

Решение

Вы всегда должны использовать параметры портлета текущего запроса. Поскольку вы используете предпочтения из конструктора вашего сессионного компонента, который обычно вызывается сначала из запроса рендеринга, предпочтения по-прежнему связаны с (устаревшим) запросом рендеринга.

Я имею в виду, как это:

public void setListMode( String listModeValue ) {
    this.listMode = ListMode.fromValue( listModeValue );
    try { 
        PortletPreferences preferences = ((PortletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getPreferences();
        preferences.setValue( LIST_MODE_KEY, listModeValue );
        preferences.store();
    }
    ...
}
Другие вопросы по тегам