View-scoped bean recreated on POST when URL parameters not used
Asked Answered
S

1

6

I have a view-scoped JSF-managed bean that's backing an xhtml view where I read one parameter from the URL using f:viewParam.

The view presents a form to the user. However, when the user submits the form by pressing the p:commandButton it seems that the view-scoped bean is recreated (I added a @PostConstruct annotation to verify this) and so doesn't remember the instance variable read from the f:viewParam (invId in the code below).

I originally navigate to the view with a GET that includes a URL parameter but the POST message that's send when the user presses the p:commandButton doesn't include the URL parameter. So I am thinking that when the JSF runtime doesn't see the URL parameter on the POST it considers this to be a different view and is recreating the JSF-managed bean. When I change the view scope to session-scoped the code works.

Here's the code:

view

<f:metadata>
    <f:viewParam name="invId" value="#{registerBean.invId}"/>
</f:metadata>
<h:form id="registrationForm">
     ....
    <p:commandButton value="register" action="#{registerBean.register}"
                     icon="ui-icon ui-icon-newwin" ajax="false"/>
</h:form>

backing bean

@ManagedBean                                      
@ViewScoped
public class RegisterBean implements Serializable {
    @ManagedProperty(value="#{invId}")
    private String invId;
    ...

update

It turns out that this wasn't related to the URL parameters at all. Following BalusC advice below I removed the c:when tags my view was using (relying on rendered attributes instead for the same effect), and now the view-scoped bean is no longer recreated and the invId field is properly retained.

Sandarac answered 8/1, 2013 at 12:36 Comment(6)
This behavior is by design. This question is a possible duplicate of: #10353141Double
@elias: this is not the same question.Chairwoman
Marcus, the @ManagedProperty is misplaced, I'd get rid of it. As to the concrete problem, please show the smallest possible view snippet which reproduces exactly this problem by just copypasting. A view scoped bean will namely be recreated when you bind a taghandler attribute (e.g. <c:if>, <ui:include>, etc) to a property of it, but this is not visible in the code posted so far, which seems to be too oversimplified. You need to provide exactly the desired information so that the problem is reproducable on a completely blank project with everything set to defaults, also by yourself.Chairwoman
@Chairwoman you're right! I read in a hurry and was caught by the recency effect.Double
@Chairwoman I am indeed using both <c:if> and <ui:include>. I will to remove them to see if the bean is recreated or not and will follow-up with the findings.Sandarac
@Chairwoman I updated the post, If you provide a token answer I will promptly accept it.Sandarac
C
8

The problem is not visible in the code posted so far, but it's for JSF 2.0/2.1 a known issue that a view scoped bean will be recreated when one of its properties is been bound to an attribute of a taghandler like JSTL <c:if> or Facelets <ui:include> or a view build time attribute of JSF component, such as id and binding, while partial state saving is enabled (as by default).

The background explanation is that any EL expressions in those attributes are executed during building and restoring the view. As view scoped beans are stored in the view and thus only available after restoring the view, such an EL expression evaluation would cause a brand new and separate view scoped bean to be created. This is basically a chicken-egg issue. It's fixed in the upcoming JSF 2.2.

There are basically 3 solutions:

  1. Change the view accordingly so that those EL expressions are only evaluated during view render time. E.g. replace <c:if>/<c:choose> by rendered.
  2. Or bind those attributes to a request scoped bean (design notice: you can just inject a view scoped bean as a managed property of a request scoped bean).
  3. Turn off partial state saving, if necessary only for the particular view.

See also:

Chairwoman answered 8/1, 2013 at 14:21 Comment(1)
While this solution didn't resolve the exact issue I was running into (I was just using an old version of Mojarra that had known bugs), this answer showed me some new concepts that I was able to use to resolve other problems our project was running into. Thanks so much, BalusC!Sabec

© 2022 - 2024 — McMap. All rights reserved.