100

When should one use the f:viewAction or preRenderView event to initialize data for a page versus using the @PostConstruct annotation? Is the rationale to use one or the other based on the type of scope of the backing bean e.g. If the backing bean is @RequestScoped, then would the choice of using f:viewAction or preRenderView over @PostConstruct to initialize your backing bean prior to rendering the view be irrelevant as the two would result in the same effect?

f:viewAction or preRenderView

<f:metadata>
  <f:viewAction action="#{myBean.initialize}" />
</f:metadata>
<f:metadata>
  <f:event type="preRenderView" listener="#{myBean.initialize}"/>
</f:metadata>

or

@PostConstruct

public class MyBean
{
    @PostConstruct
    public void initialize()
    {

    }
}
Subodh Joshi
  • 10,006
  • 23
  • 84
  • 177
BestPractices
  • 12,101
  • 27
  • 90
  • 134

2 Answers2

124

When should one use the f:viewAction or preRenderView event to initialize data for a page verses using the @PostConstruct annotation?

Use the <f:viewAction> when you want to execute a method before the HTML is been rendered. This is particularly useful if you want to perform actions based on model values set by <f:viewParam> during update model values phase. Namely, they are not available at the moment the @PostConstruct runs. In JSF 2.0/2.1, this tag didn't exist and you have to use the preRenderView workaround.

If the backing bean is @RequestScoped, do they effectively do the exact same thing? (and so then it is up to developer choice? (@PostConstruct seems "cleaner").

No, they do definitely not effectively do the same thing. The @PostConstruct is intented to perform actions directly after bean's construction and setting of all injected dependencies and managed properties such as @EJB, @Inject, @ManagedProperty, etc. Namely, the injected dependencies are not available inside the bean's constructor. This will thus run only once per view, session or application when the bean is view, session or application scoped. The <f:viewAction> is by default only invoked on initial GET request, but can via onPostback="true" attribute be configured to be invoked on postback requests as well. The preRenderView event is invoked on every HTTP request (yes, this also includes ajax requests!).

Summarized, use @PostConstruct if you want to perform actions on injected dependencies and managed properties which are set by @EJB, @Inject, @ManagedProperty, etc during bean's construction. Use <f:viewAction> if you also want to perform actions on properties set by <f:viewParam>. If you're still on JSF 2.0/2.1, use preRenderView instead of <f:viewAction>. You can if necessary add a check on FacesContext#isPostback() to perform the preRenderView action on initial request only.

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • Thanks. Sorry I edited my original question while you were writing the response... – BestPractices Mar 23 '12 at 18:31
  • I mentioned bean scope because @PostConstruct would only be called once if the bean were SessionScoped (at the time bean is first created) but preRenderView would be called every time the page is accessed. Or did I get that wrong? – BestPractices Mar 23 '12 at 18:41
  • Yes, that's correct. The pre render view event is called on invoke action phase. The post construct is invoked after bean's construction. A session scoped bean is not constructed on every HTTP request. – BalusC Mar 23 '12 at 18:43
  • I was wondering my my method was being called during ajax requests. the isPostBack() call saved the day!! – jacosta Oct 29 '13 at 20:08
  • For the sake of completeness, we should mention [Omnifaces' `@Param`](https://showcase.omnifaces.org/cdi/Param): "For HTTP request parameters it's basically like ``, but with the major difference that the injected parameter is directly available during `@PostConstruct`, allowing a much easier way of processing without the need for a `` or `` in the view." – Jens Piegsa Sep 09 '20 at 08:29
1

Do you need to initialize managed bean's properties? --> Then, use @PostConstruct Otherwise, do you need to work with params passed from other view? --> Then, use "preRenderView"

Val Martinez
  • 543
  • 5
  • 14