Primefaces: условно визуализированный компонент не отправляется

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

Код довольно прост:

<h:form id="form">
    <p:layout id="layout">
        ...
        <p:layoutUnit id="layoutUnit">
            ...
            <p:panel id="panel">
                <p:outputPanel id="container1">
                    <p:selectOneMenu id="value1" value="#{bean.value1}">
                        <f:selectItem itemValue="1"/>
                        <f:selectItem itemValue="2"/>
                        <f:selectItem itemValue="3"/>
                        <f:selectItem itemValue="18"/>
                        <p:ajax event="change" update="container2"/>
                    </p:selectOneMenu> 
                </p:outputPanel>

                <p:outputPanel id="container2">
                    <p:inputText id="value2" 
                                 value="#{bean.value2}" 
                                 rendered="#{bean.value1 eq 18}"
                                 >
                    </p:inputText>
                </p:outputPanel>
            </panel>

            <div id="buttons">
                <p:commandButton id="commandButton" action="#{bean.save}" value="save" />
            </div>
        </layoutUnit>
    </layout>
</form>

Пробовал возможные решения:

Я могу придумать несколько сценариев, вызывающих такое поведение:

  1. «Rendered», кажется, переоценивает на основе значений в поддерживающем bean-компоненте, а не на новых значениях, заданных в пользовательском интерфейсе (если по умолчанию 1, то при отправке снова будет 1, а не 18). Таким образом, компонент не отправляется.
  2. Добавленный компонент неправильно добавлен в форму и, следовательно, не отправлен.
  3. ?

Вариант 1 кажется наиболее вероятным, но может ли кто-нибудь указать мне правильное направление?

Я работаю с WAS8.5 (поэтому JSF2.0), Primefaces и CDI.


person hhschoone    schedule 22.07.2015    source источник
comment
потому что он конфликтует с CDI Хм? Другими словами, вы еще не используете JSF 2.2 и не можете выполнить обновление? JSF 2.2 имеет аннотацию @ViewScoped, совместимую с CDI.   -  person BalusC    schedule 22.07.2015
comment
Опишите, как должен работать пользовательский интерфейс, что вы делаете в пользовательском интерфейсе и в какой момент ваши ожидания не оправдываются. Непонятно, что должна выполнять ваша rendered привязка.   -  person Vsevolod Golovanov    schedule 22.07.2015
comment
@VsevolodGolovanov: случай OP не работает, потому что его bean-компонент имеет область действия запроса, а не область просмотра. Теперь OP в основном спрашивает, как поддерживать состояние с областью видимости, не ограничивая область видимости компонента. Список нескольких сценариев не имеет смысла. Это уже давно объяснено, в частности, вторая ссылка, упомянутая OP (которая, таким образом, по сути является дубликатом вопроса в его текущей форме, если OP не разрабатывает свою конкретную проблему с @ViewScoped)   -  person BalusC    schedule 22.07.2015
comment
Мы работаем с WAS8.5 и, следовательно, с JSF2.0. Я не уверен, можно ли перейти на 2.2, поэтому ищу другое решение. При использовании @Viewscoped изменение в AJAX-компоненте приводит к ошибке типа javax.faces.FacesException: Exception while validating component with path ... Или это не связано?   -  person hhschoone    schedule 22.07.2015
comment
Почему вы изначально пометили вопрос (ненужным) тегом [java-ee-7], когда на самом деле используете WAS 8.5 (который не является Java EE 7)? Вы управляете bean-компонентами с помощью JSF @ManagedBean или CDI @Named? Таким образом, вы имели в виду, что столкнулись именно с этим исключением? (который действительно потенциально связан и подлежит ответственности при сохранении @ViewScoped кстати) Как именно это исключение связано с конфликтами с CDI?   -  person BalusC    schedule 22.07.2015
comment
Да, извините - я должен был упомянуть, что я относительно новичок в мире Java, так сказать, учусь на работе. Тем не менее, я использую CDI @Named. Изменение этого параметра на @ViewScoped приводит к исключению, упомянутому выше. Тем не менее, вы говорите, что проблема должна быть решена с помощью @ViewScoped вместо @Named, чтобы не вызывать ее при работе как с JSF, так и с CDI?   -  person hhschoone    schedule 22.07.2015
comment
Использование @ConversationScoped в дополнение к @Named кажется (?) Решением - делать что-то сравнимое с @ViewScoped. Я просто добавил код из примера сюда . Единственное, в чем я сейчас не уверен, так это в том, правильно ли завершился разговор. tbc   -  person hhschoone    schedule 22.07.2015
comment
@ViewScoped и @Named не исключают друг друга. @ManagedBean и @Named есть. Вы можете просто использовать @Named @ViewScoped, вам нужно только следить за тем, чтобы вы использовали CDI @ViewScoped, а не JSF @ViewScoped. Только CDI @ViewScoped доступен только начиная с JSF 2.2, или вам нужно скачать OmniFaces.   -  person BalusC    schedule 23.07.2015
comment
PS: в случае, если более одного человека прокомментировали сообщение, используйте @nickname (без тегов кода), чтобы ответить конкретному человеку (в противном случае заинтересованное лицо не будет уведомлено об ответе на комментарий и увидит его позже только стечение обстоятельств).   -  person BalusC    schedule 23.07.2015


Ответы (1)


Решением является использование CDI @ConversationScoped в дополнение к @Named. Эта область работает аналогично @ViewScoped из JSF.

Чтобы он заработал, я просто добавил код из примера здесь. Вкратце:

Bean.java

@Named
@ConversationScoped
public class Bean implements Serializable{

    @Inject
    private Conversation conversation;

    Bean values, getters & setters

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

    public String endConversation(){
        if(!conversation.isTransient()){
            conversation.end();
        }
    }

    public String navigateAwayFromScreen(){
        endConversation();
    }
}

beanOutput.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <f:event listener="#{bean.initConversation}" type="preRenderView"/>

    <h:form id="form">
        <p:layout id="layout">
            ...
            <p:layoutUnit id="layoutUnit">
                ...
                <p:panel id="panel">
                    <p:outputPanel id="container1">
                        <p:selectOneMenu id="value1" value="#{bean.value1}">
                            <f:selectItem itemValue="1"/>
                            <f:selectItem itemValue="2"/>
                            <f:selectItem itemValue="3"/>
                            <f:selectItem itemValue="18"/>
                            <p:ajax event="change" update="container2"/>
                        </p:selectOneMenu> 
                    </p:outputPanel>

                    <p:outputPanel id="container2">
                        <p:inputText id="value2" 
                                     value="#{bean.value2}" 
                                     rendered="#{bean.value1 eq 18}"
                                     >
                        </p:inputText>
                    </p:outputPanel>
                </panel>

                <div id="buttons">
                    <p:commandButton id="commandButton" action="#{bean.navigateAwayFromScreen}" value="Go away!" />
                </div>
            </layoutUnit>
        </layout>
    </form>
</html>

Теперь диалог начинается, когда вы открываете страницу (из-за того, что initConversation вызывается из верхней части beanOutput.xhtml) и заканчивается, когда вы нажимаете кнопку navigateAwayFromScreen.

(Однако, если вы умеете работать с JSF2.2, должно быть возможно использовать @ViewScoped в сочетании с CDI. (Я говорю «следует»: я не в ситуации, когда нужно выполнить обновление. Но это может быть полезно для другие на осмотр)).

person hhschoone    schedule 23.07.2015