Метод PostConstruct компонента ConversationScoped вызывается при каждом запросе

Что ж, я использую ConversationScoped и надеюсь, что PostConstruct вызывается только один раз в начале разговора, см.

@Named("disciplinaDetalheMB")
@ConversationScoped
public class DisciplinaDetalheMBImpl {

    private static final long serialVersionUID = 1L;

    @Inject
        private Conversation conversation;

    @Inject
    @AnBasicBO
    private BasicBO boPadrao;

@PostConstruct
    public void postConstruct() {
    logger.debug("Iniciando PostConstruct...");
    init();
    beginConversation();
    }

public String salvarAndRedirecionar() {
    salvar();
    if (!FacesContext.getCurrentInstance().isValidationFailed()) {
        return goToLastPage() + "?faces-redirect=true";
    } else {
        return "";
    }
    }


private void beginConversation() {
    if (!conversation.isTransient()) {
        endConversation();
    }
    conversation.begin();
    if (conversation.isTransient()) {
        throw new RuntimeException("A conversão não foi iniciada corretamente");
    }
    SessionContext.getInstance().setAttribute("cid", conversation.getId());

    }

    public BasicBO getBoPadrao() {
        return boPadrao;
    }

    public void setBoPadrao(BasicBO boPadrao) {
        this.boPadrao = boPadrao;
    }

}

Таким образом, когда мой резервный компонент создается, диалог инициализируется, а CID сохраняется в сеансе для последующего использования. У меня есть commandButton «сохранить» в моем XHTML, и когда эта кнопка вызывается, PostConstruct снова вызывается, я не знаю, почему:

<h:commandLink
            action="#{managedBeanName.salvarAndRedirecionar()}"
            styleClass="btn btn-info pull-right" value="Salvar">
            <f:ajax execute="@form" />
        </h:commandLink>

Я отметил, что сгенерированный HTML:

<a id="formManterDisciplina:j_idt44:j_idt46" href="#" onclick="mojarra.ab(this,event,'action','@form',0);return false" class="btn btn-info pull-right" name="formManterDisciplina:j_idt44:j_idt46">Salvar</a>

Итак, я понимаю, что "href=#" позволяет избежать выполнения onlick. Я думаю, что это проблема, но я не знаю, как исправить. Напоминаем: метод salvarAndRedirectionar() никогда не вызывается, потому что перед ним всегда вызывается postConstruct.

2) У меня есть еще вопрос: если я начинаю разговор и не заканчиваю, есть какая-то проблема? Иногда я не хочу заканчивать разговор вручную, потому что у меня есть только ОДНА СТРАНИЦА, я только начинаю.


person Ronaldo Lanhellas    schedule 18.10.2015    source источник
comment
Какова область действия этого класса? почему бы не показать нам больше определения класса?   -  person John Ament    schedule 19.10.2015
comment
Это n-й раз, когда вам пришлось удалить тег [java] из вашего вопроса [jsf]. Не могли бы вы принять это как подсказку, чтобы больше не добавлять тег [java] в будущем вопросе [jsf]? Используйте тег [java] только в том случае, если у вас есть проблема, которая может быть воспроизведена в классе приложения Java с помощью метода main(). Если у вас есть такая проблема, вам следует пересмотреть актуальность [jsf] и других тегов, связанных с Java EE.   -  person BalusC    schedule 19.10.2015


Ответы (1)


Причина, по которой у вас возникает эта проблема, заключается в том, что вы вызываете метод начала диалога в методе postconstruct компонента области диалога. Таким образом, беседа будет переведена в состояние длительного выполнения во время фазы ответа на визуализацию, а не до нее. Проблема заключается в том, что параметр CID отображается в элементе HTML-формы, но в этот момент диалог все еще находится в переходном состоянии, поскольку после запроса метод postconstruct еще не был вызван. Метод postconstruct вызывается при перерисовке элемента commandLink, а затем уже слишком поздно, и элемент HTML-формы не будет содержать параметр CID:

<form id="yourForm" name="yourForm" method="post" action="/path/to/yourPage.xhtml" enctype="application/x-www-form-urlencoded">

Таким образом, решение состоит в том, чтобы переместить начало разговора в точку, предшествующую фазе Render Response. Вы можете сделать это с тегом f:viewAction, если вы используете JSF 2.2, или с тегом f:event, если вы используете более старую версию.

И тогда вы увидите параметр CID, отображаемый внутри вашего элемента HTML-формы, например:

<form id="yourForm" name="yourForm" method="post" action="/path/to/yourPage.xhtml?cid=1" enctype="application/x-www-form-urlencoded">

  • Если вы используете тег f:event:

На вашей странице:

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

В вашем резервном компоненте:

public void initConversation(){
    if (!FacesContext.getCurrentInstance().isPostback() && conversation.isTransient()) {
          conversation.begin();
    }
}
  • Если вы используете тег f:viewAction:

На вашей странице:

<f:metadata>
    <f:viewAction action="#{disciplinaDetalheMB.initConversation}" />
</f:metadata>

В вашем резервном компоненте:

public void initConversation(){
    if (conversation.isTransient()) {
          conversation.begin();
    }
}

Что касается вашего второго вопроса, то нет большой проблемы в том, чтобы не завершить разговор, потому что у него есть тайм-аут, такой как сеанс HTTP. Вы можете установить значение тайм-аута в зависимости от вашей стратегии управления ресурсами сервера и желаемого времени жизни для простоя разговора. В любом случае, когда у вас есть только одна страница, вам лучше использовать компонент поддержки с областью видимости.

person Javier Haro    schedule 19.10.2015
comment
сработало очень хорошо, спасибо. Но я не могу смешивать @ ViewScoped (аннотация jsf) с @ Named (аннотация CDI), возникают ошибки. Можешь мне помочь ? - person Ronaldo Lanhellas; 20.10.2015
comment
Если вы используете JSF 2.2, используйте javax.faces.view.ViewScoped, но не javax.faces.bean.ViewScoped. - person Javier Haro; 20.10.2015
comment
Теперь работаю, еще раз спасибо. Но я читал в какой-то статье, что не рекомендуется смешивать аннотации JSF и аннотации CDI, это правда? Если да, то почему? Нормально работают без проблем. - person Ronaldo Lanhellas; 20.10.2015
comment
Лучше всего использовать в модели только управляемые компоненты CDI. Вот почему JSF 2.2 представил новую область видимости представления (javax.faces.view.ViewScoped) с использованием переносимого расширения CDI. - person Javier Haro; 20.10.2015