@PostConstruct method called twice for the same request

29,453

Solution 1

That can happen if you have multiple frameworks managing the same bean class. E.g. JSF and CDI, or JSF and Spring, or CDI and Spring, etc. Doublecheck your configuration and annotations on the bean.

That can also happen if you're using CDI and are using multiple @Named annotations throughout the class. For example, a @Named straight on the class to register it as a managed bean and another one on a @Produces getter method. You'd need to ask yourself whether that is really necessary. You could also just use #{bean.someObject} instead of #{someObject}.

@Named
@RequestScoped
public class Bean {

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

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

}

That can also happen if your managed bean extends some abstract class which has in turn also a @PostConstruct on the method. You should remove the annotation from it. Alternatively, you should make the init method abstract and not have @PostConstruct on the implementing bean:

public abstract class BaseBean {

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

    public abstract void init();

}

Solution 2

It is possible that the both init() method and @PostConstruct methods are firing and causing this behavior. Try changing the name of the init() method and/or putting it private. I think that this may be related to your problems:

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

I also found a good post about debugging JSF life cycles here: Debug JSF lifecycle

Share:
29,453

Related videos on Youtube

Ionut
Author by

Ionut

Updated on July 09, 2022

Comments

  • Ionut
    Ionut almost 2 years

    I'm using JSF 2.0 with GlassFish 3.0.

    I have the following Managed Bean:

    @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");
        }
    }
    

    From the the overview.xhtml file I'm calling different attributes or methods from my OverviewController.

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

    Everything works just fine but the problem is on the Log File:

    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
    

    As you can see, The init() method is called twice in the same request for no reason what so ever. From what I know, any method annotated with PostConstruct is called once every request. Am I wrong?

    EDIT: No AJAX is used on the page. I checked the number of requests with firebug. There are tree requests made:

    • 1.One for the javax.faces.resource (GET)
    • 2.One for the css file (GET)
    • 3.One for overview.xhtml (GET)
    • Kushan
      Kushan over 12 years
      Are you mean ClassFish or GlassFish?
    • MrKiane
      MrKiane over 12 years
      Are you performing any Ajax calls? Use FireBug or similar add on to find out how many requests the browser is actually making.
    • Ionut
      Ionut over 12 years
      @PederN I updated the question.
    • MrKiane
      MrKiane over 12 years
      On this page there are some tips for debugging JSF lifecycles. Check it out, maybe it is something there that can help you balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html
    • Ionut
      Ionut over 12 years
      Thanks! Sadly I couldn't find there anything which could explain my problem. It seems that all the methods annotated with @PostConstruct are called twice in Invoke Application or RenderResponse
    • MrKiane
      MrKiane over 12 years
      What if you name the init() method something else, such as myInit()? init() method was used before to initialize servlets (AFAIK), could it be that Glassfish is running init() in one state of the life cycle and @PostConstruct in another? Is this related? javahowto.blogspot.com/2011/07/…
  • BalusC
    BalusC over 12 years
    This makes no sense. A JSF managed bean is not a HttpServlet implementation.
  • MrKiane
    MrKiane over 12 years
    I meant that depending on configuration it may cause the system to get confused and fire on both methods. Maybe it was a long shot though. Thanks for your clarification.
  • Ionut
    Ionut over 12 years
    I tried removing the annotation but then the init() would be ignored. As BalusC said it seems that there is no init() method in a managed bean.
  • BalusC
    BalusC over 12 years
    @Peder: JSF has absolutely no special treatment for methods called init(). You're confusing with HttpServlet#init(). Please re-read the javahowto article which you linked yourself.
  • Ionut
    Ionut over 12 years
    Thanks! I don't have multiple frameworks but this helped me to understand what the problem was. All my ManagedBeans extend a BaseController. This BaseController has a @PostConstruct init() method which I thought it would be override by the other ManagedBeans' PostConstruct init(). It seems though that both init() are called. It all makes sense now.. Thank you!
  • BalusC
    BalusC over 12 years
    You should not have @PostConstruct in the BaseController class. Remove it.
  • Mr.J4mes
    Mr.J4mes over 12 years
    @BalusC: I have a small side question. Regarding using JSF and CDI on the same bean, if I use @Inject to inject a CDI bean into a @ManagedBean, will the @PostConstruct method be called twice? I'm not quite sure how to apply multiple framework on the same bean. I thought that the framework was decided by annotated the bean with @ManagedBean, @Named, etc.
  • Half Blood Prince
    Half Blood Prince almost 8 years
    @BalusC I have the same problem. I have defined @PostConstruct method inside @Controller class. Is there any problem in it? Actually, I want to start my scheduler on app deployment. Is there any other way?