Метод @PostConstruct вызывается дважды для одного и того же запроса - PullRequest
17 голосов
/ 31 января 2012

Я использую JSF 2.0 с GlassFish 3.0.

У меня есть следующий управляемый компонент:

@ManagedBean
@RequestScoped
public class OverviewController{

    private List<Event> eventList;

    @PostConstruct
    public void init(){
        System.out.println("=> OverviewController - init() - enter");

        System.out.println("=< OverviewController - init() - exit");
    }
}

Из файла Overview.xhtml я вызываю различные атрибуты или методы из моего OverviewController.

<ui:repeat var="event" value="#{overviewController.eventList}">
    ...
</ui:repeat>

Все работает просто отлично, но проблема в файле журнала:

INFO: Enter : RESTORE_VIEW 1
INFO: Exit : RESTORE_VIEW 1

INFO: Enter : RENDER_RESPONSE 6
INFO: => OverviewController - init() - enter
INFO: => Overview Controller - updateSelectedTab() - enter
INFO: =< Overview Controller - updateSelectedTab() - exit
INFO: =< OverviewController - init() - exit
INFO: => OverviewController - init() - enter
INFO: => Overview Controller - updateSelectedTab() - enter
INFO: =< Overview Controller - updateSelectedTab() - exit
INFO: =< OverviewController - init() - exit
INFO: Exit : RENDER_RESPONSE 6

Как видите, метод init () вызывается дважды в одном и том же запросе без какой-либо причины. Из того, что я знаю, любой метод, помеченный PostConstruct , вызывается один раз при каждом запросе. Я не прав?

EDIT: AJAX не используется на странице. Я проверил количество запросов с помощью firebug. Сделано дерево запросов:

  • 1. Один для javax.faces.resource (GET)
  • 2. Один для файла CSS (GET)
  • 3. Один для обзора. Xhtml (GET)

Ответы [ 2 ]

21 голосов
/ 31 января 2012

Это может произойти, если у вас есть несколько сред, управляющих одним и тем же классом компонента.Например, JSF и CDI, или JSF и Spring, или CDI и Spring и т. Д. Проверьте вашу конфигурацию и аннотации на компоненте.

Это также может произойти, если вы используете CDI и используете несколько @Named аннотаций в классе.Например, @Named прямо в классе, чтобы зарегистрировать его как управляемый компонент, а другой - в методе @Produces getter.Вы должны спросить себя, действительно ли это необходимо .Вы также можете просто использовать #{bean.someObject} вместо #{someObject}.

@Named
@RequestScoped
public class Bean {

    @PostConstruct
    public void init() {
        // ...
    }

    @Named
    @Produces
    public SomeObject getSomeObject() {
        // ...
    }

}

Это также может произойти, если ваш управляемый компонент расширяет некоторый абстрактный класс, который, в свою очередь, также имеет @PostConstruct в методе.Вы должны удалить аннотацию из него.В качестве альтернативы вы должны сделать метод init абстрактным, а не иметь @PostConstruct в реализующем компоненте:

public abstract class BaseBean {

    @PostConstruct
    public void postConstruct() {
        init();
    }

    public abstract void init();

}
2 голосов
/ 31 января 2012

Возможно, что оба метода init() и @PostConstruct вызывают и вызывают такое поведение. Попробуйте изменить имя метода init() и / или поставить его private. Я думаю, что это может быть связано с вашими проблемами:

http://javahowto.blogspot.com/2011/07/servlet-init-method-vs-postconstruct.html

Я также нашел хороший пост об отладке жизненных циклов JSF здесь: Отладка жизненного цикла JSF

...