ViewParam vs @ManagedProperty(value = "#{param.id}")
Asked Answered
L

2

101

What is the difference between defining View Params like this:

<f:metadata>
  <f:viewParam name="id" value="#{someBean.id}"/>
</f:metadata>

And defining the property in the ManagedBean like this:

@Inject @ManagedProperty(value = "#{param.id}")
private Integer id;
Legged answered 3/2, 2011 at 16:45 Comment(0)
K
148

<f:viewParam>:

  • Sets the value during update model values phase only (since it extends UIInput).

  • The set value is not available during @PostConstruct, so you need an additional <f:event type="preRenderView" listener="#{bean.init}" /> inside the <f:metadata> to do initialization/preloading based on the set values. Since JSF 2.2 you could use <f:viewAction> for that instead.

  • Allows for nested <f:converter> and <f:validator> for more fine-grained conversion/validation. Even a <h:message> can be attached.

  • Can be automatically included as GET query string in outcome target URLs using includeViewParams attribute of <h:link> or includeViewParams=true request parameter in any URL.

  • Can be used on a @RequestScoped bean, but it requires the bean to be @ViewScoped if you want the view parameters to survive any validation failures caused by forms enclosed in the view, otherwise you need to manually retain all request parameters for the subsequent requests by <f:param> in the UICommand components, because the <f:viewParam> will be set on every request.

Example:

<f:metadata>
    <f:viewParam id="user_id" name="id" value="#{bean.user}"
        required="true" requiredMessage="Invalid page access. Please use a link from within the system."
        converter="userConverter" converterMessage="Unknown user ID."
    />
</f:metadata>
<h:message for="user_id" />

with

private User user;

and an @FacesConverter("userConverter"). Invoking page by http://example.com/context/user.xhtml?id=123 will pass the id parameter through the converter and set the User object as a bean property.


@ManagedProperty:

  • Sets the value immediately after bean's construction.

  • Set value is available during @PostConstruct which allows easy initialization/preloading of other properties based on the set value.

  • Does not allow for declarative conversion/validation in view.

  • Does not support being automatically included in outcome target URLs.

  • Can be used on a bean of any scope, but it will be set only during bean's construction instead of on every request.

Example:

@Inject @ManagedProperty("#{param.id}")
private Long id;

private User user;

@EJB
private UserService userService;

@PostConstruct
public void init() {
    user = userService.find(id);
}

Do note that you have to manage conversion and validation yourself whenever user is null by fiddling with FacesContext#addMessage() inside the @PostConstruct method. Also note that when #{param.id} is not a valid number, then an exception will be thrown before @PostConstruct is hit. If you want to deal with it, then you'd probably better make it a private String id. But much better is to use <f:viewParam>.


You can use them both when both @PostConstruct and includeViewParams are mandatory. You only won't be able to apply fine-grained conversion/validation anymore.


See also:

Kozloski answered 3/2, 2011 at 17:6 Comment(7)
There are other alternative to retrieve request parameters in exceptional cases: FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("parametername");Concordant
@angel: Only when the bean has a broader scope than request scope which makes @ManagedProperty on a request parameter impossible.Kozloski
hi @Kozloski I do rely on the value of id retrieved from param.id using managedproperty on a second post. How can I include it using f:param? thanks a lotThorite
what do you mean that the set value is not available during @PostConstruct. If not then, when? How do you use <f:viewAction> in this scenario?Thacker
@thufir: It's set during update model values phase. The postconstruct runs far before that, directly after bean's construction and dependency injection. It is available in the listener method which is invoked by <f:event type="preRenderView"> or the upcoming JSF 2.2 <f:viewAction>.Kozloski
Can you use f:viewParam for multiple GET parameters?Halbeib
@feder: stackoverflow.com/questions/7794149/…Kozloski
R
6

2 other differences:

  • @ManagedProperty is usable only with beans managed by JSF, not with beans managed by CDI (@Named);
    • <f:viewParam> works only with parameters of GET requests.
Rasla answered 6/12, 2012 at 15:44 Comment(1)
Therefore you could use the annotation: org.omnifaces.cdi.ParamJelle

© 2022 - 2024 — McMap. All rights reserved.