62

Is there a way to execute a JSF managed bean action when a page is loaded?

If that's relevant, I'm currently using JSF 1.2.

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
DD.
  • 19,793
  • 49
  • 140
  • 237
  • duplicate http://stackoverflow.com/questions/1686821/execute-backing-bean-action-on-load/1695823#1695823 – Bozho Mar 16 '10 at 06:14
  • 1
    Not sure though, there is ambiguity in the question. As long as he don't explicitly state "download file on page load", or "fire new request on page load", or so, then the mentioned topic is not necessarily a dupe of this. – BalusC Mar 16 '10 at 12:57
  • 2
    Correct answer is given here http://stackoverflow.com/a/1710413/362752 – Nikola Aug 02 '12 at 14:58

4 Answers4

96

JSF 1.0 / 1.1

Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.

public Bean() {
    // Do your stuff here.
}

JSF 1.2 / 2.x

Use @PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.

@PostConstruct
public void init() {
    // Do your stuff here.
}

This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.

JSF 2.0 / 2.1

Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a @PostConstruct is perfectly fine too.

<f:metadata>
    <f:viewParam name="foo" value="#{bean.foo}" />
    <f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() { 
    // Do your stuff here.
}

JSF 2.2+

Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a @PostConstruct is perfectly fine too.

<f:metadata>
    <f:viewParam name="foo" value="#{bean.foo}" />
    <f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() { 
    // Do your stuff here.
}

Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).

public String onload() { 
    // Do your stuff here.
    // ...
    return "some.xhtml";
}

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • your answer is great and fit to my need... **But one question...** In my D. constructor I am adding such a content that will be visible on view side (on the same jsp). In this case my jsp doesn't view this information on very first time. But if I reload a page that content is visible. Can we handle this thing any way? – Ketan Apr 20 '12 at 18:06
  • This answer will only work once if I have a session scope. Is there a better way to implement this for session scope bean? – huahsin68 Feb 26 '13 at 08:38
  • @huahsin68, the answers provided are going to work as expected. As BalusC said, use the last two examples for beans that have a wider scope than **view**-scope. For those curious about where to place the `f:metadata` information in a `ui:composition` page: Right after the `ui:composition` and **before** a possible `ui:define` or alike tags. – DanielK Sep 07 '15 at 12:12
  • you should use "f:event" instead of "f:viewAction", if you are using jsf 2.0+ – Gökhan Polat Jun 06 '17 at 13:30
14

Another easy way is to use fire the method before the view is rendered. This is better than postConstruct because for sessionScope, postConstruct will fire only once every session. This will fire every time the page is loaded. This is ofcourse only for JSF 2.0 and not for JSF 1.2.

This is how to do it -

<html xmlns:f="http://java.sun.com/jsf/core">
      <f:metadata>
          <f:event type="preRenderView" listener="#{myController.onPageLoad}"/>
      </f:metadata>
</html>

And in the myController.java

 public void onPageLoad(){
    // Do something
 }

EDIT - Though this is not a solution for the question on this page, I add this just for people using higher versions of JSF.

JSF 2.2 has a new feature which performs this task using viewAction.

<f:metadata>
    <f:viewAction action="#{myController.onPageLoad}" />
</f:metadata>
stolen_leaves
  • 1,177
  • 9
  • 18
11

@PostConstruct is run ONCE in first when Bean Created. the solution is create a Unused property and Do your Action in Getter method of this property and add this property to your .xhtml file like this :

<h:inputHidden  value="#{loginBean.loginStatus}"/>

and in your bean code:

public void setLoginStatus(String loginStatus) {
    this.loginStatus = loginStatus;
}

public String getLoginStatus()  {
    // Do your stuff here.
    return loginStatus;
}
Amin Bahiraei
  • 143
  • 1
  • 2
  • 5
    So, you're using alone session scoped beans? That's a Bad Practice. Plus, your example is poor. Getters can be called more than once in bean's life and shouldn't be abused to execute business stuff. Just use a request scoped bean and do the job in constructor or `@PostConstruct`. – BalusC Nov 23 '10 at 13:57
2

calling bean action from a will be a good idea,keep attribute autoRun="true" example below

<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#{bean.action}" partialSubmit="true" update=":form" />
sijo jose
  • 1,139
  • 1
  • 7
  • 8