0

Environment:

  • Jboss 5.2
  • Java 7
  • JSF 2.1.2
  • Primefaces 6.2
  • Mojarra (1.2_13-b01-FCS)

I want to load a menu generated in @PostConstruct method in ViewScope bean but when the web page is loaded the menu is void.

The page persona.xhtml is loaded from a redirect from another web page and the PersonaBean has ViewScope. PersonaBean init() @PostConstruct is executed but no values are loaded in the web page.

The specific bean CustomMenuBean (view scope) is loaded but the CustomMenuBean.menu is null in web page but it has the menu in the bean (when I stop there in debug mode CustomMenuBean.menu is correctly loaded).

So I tried to update frmMenus with a button for testing purposes and it works well after web page refresh with following code.

<p:commandButton value="update" action="#{personaBean.doNothing}"  process=":frmMenus" update=":frmMenus"/>

Web page persones.xhtml

...
<p:dataTable id="lstPersones" var="item" value="#{personesBean.items}"...>
    <p:ajax event="rowSelect" listener="#{personesBean.onRowSelect}"/>
...

PersonesBean.java

@ViewScoped
@ManagedBean
public class PersonesBean ...
...
    @Override
    public void onRowSelect(SelectEvent event) {
        ...
        HttpServletRequest origRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        String ctxPath = origRequest.getContextPath();
        FacesContext.getCurrentInstance().getExternalContext().redirect(ctxPath + "\gestio\persona.xhtml");
...

Web page persona.xhtml

...
<h:form id="frmMenus">
    <div class="layout-menu-container #{usuariPreferenciesBean.menuClass}">
        <div class="nano">
            <div class="nano-content menu-scroll-content">
                <ui:include src="menu_profile.xhtml"/>

                <pu:menu id="mnu_custom" widgetVar="mnu_custom" model="#{customMenuBean.menu}"/>
                <p:separator/>
            </div>
        </div>
    </div>
</h:form>

 <h:form id="frmPersona">
    <!-- person data -->
 </h:form>
 ...

PersonaBean.java

@ViewScoped
@ManagedBean
public class PersonaBean...
...
@ManagedProperty(value = "#{customMenuBean}")
private CustomMenuBean cstmMenuBean; //View scope Bean to store menu

@PostConstruct
public void init() {

    super.init(Persona.class);
    super.setService(service);

    cstmMenuBean.generateMenu(); //create a DefaultMenuModel()

}
...

I don't know what I'm missing.

Joe
  • 7,749
  • 19
  • 60
  • 110
  • 2
    Your question is unclear to me so far. In which moment should the component be updated? An AJAX interaction is required to update components. And are you sure about JSF version 1.0? Primefaces [declares to depend on 2.0](https://primefaces.github.io/primefaces/8_0/#/gettingstarted/dependencies) at least. – Selaron Feb 27 '20 at 11:02
  • 1
    So you want to update a form/component from the bean? As you use PrimeFaces, you can use `PrimeFaces.current().ajax().update("foo:bar");`. also see [this](https://stackoverflow.com/questions/11365094/can-i-update-a-jsf-component-from-a-jsf-backing-bean-method) question – fuggerjaki61 Feb 27 '20 at 11:22
  • Does this answer your question? [Can I update a JSF component from a JSF backing bean method?](https://stackoverflow.com/questions/11365094/can-i-update-a-jsf-component-from-a-jsf-backing-bean-method) – fuggerjaki61 Feb 27 '20 at 11:22
  • 1
    Firing another update is probably not the way you want to go. When you load the page, your `@PostConstruct` method is refreshing the component tree and adding something under `:frMenus` and you essentially want to mark it to be updated on the page? Am I understanding you correctly? The solution is to not do this under `@PostConstruct`, rather you want to plug yourself into the lifecycle prior to the component being processed - but is this what you are after ? Then it's actually quite simple and I can easily produce some example code. – Adam Waldenberg Feb 27 '20 at 11:38
  • @AdamWaldenberg I create the menu on PostConstruct because is dynamically generated on bean load. The problem I have is that the web page has no information about menu but is correctly loaded in the bean. Where should menu be loaded? How? – Joe Feb 27 '20 at 12:00
  • @Selaron I was wrong about the jsf version, I was using 2.1.2. What I want, it is just to generate the menu before the web is showed, and show it when the web page is loaded. – Joe Feb 27 '20 at 12:06
  • The question is really vague, but I guess the OP is looking for ``. – BalusC Feb 27 '20 at 16:46
  • I'll write up an answer later tonight. A remoteCommand is probably not the way to go @BalusC as that will fire up a a seperate request. The proper way is to connect the menu component to a preRender event instead of relying on `@PostConstruct`. – Adam Waldenberg Feb 27 '20 at 19:20
  • @Joe Could you show us what you are doing in @PostConstruct? That would help in finding the appropriate solution. There is a big difference between updating model values and the component tree for example. – Adam Waldenberg Feb 28 '20 at 05:57
  • @AdamWaldenberg I updated the question with the code of PostConstruct. There I'm creating a DefaultMenuModel that I want to show when the page is loaded and it seems simple but I'm missing something – Joe Feb 28 '20 at 07:38
  • To create the DefaultMenuModel (I guess it modifies the component tree and model values as well) – Joe Feb 28 '20 at 07:56
  • 1
    Nope, it doesn't modify the view (the component tree). As I said, your problem is really vague. You need to write down the functional requirements for problem X instead of to ask how to approach the Y problem of your https://xyproblem.info. A `@PostConstruct` is a perfectly fine place to initialize the model. Please demonstrate your X problem with a *real* [mcve] which is created as per instructions in https://stackoverflow.com/tags/jsf/info. Also see PrimeFaces showcase site for real examples. – BalusC Feb 28 '20 at 09:32
  • @BalusC I tried to remake the question and simplified the explanation, I hope is more understandable. – Joe Feb 28 '20 at 12:10
  • @Joe At first glance this looks mostly fine... How is PersonBean defined and under what scope ? Is it a `@ManagedBean`. I'm asking, because I have observed some very strange issues with `@PostConstruct` and the old JSF bean API in the past. For example, https://github.com/eclipse-ee4j/glassfish/issues/15148 – Adam Waldenberg Feb 28 '20 at 12:15
  • @AdamWaldenberg the bean has the annotations ViewScoped and ManagedBean – Joe Feb 28 '20 at 12:25
  • @Joe First thing that hits me - are you using the correct `@ViewScoped` from the right package ? There is one defined for CDI and another for the old JSF API that is used together with `@ManagedBean`. – Adam Waldenberg Feb 28 '20 at 13:11
  • are you initing the menu after a login? I have some similar issues where the menu is only updating after a page refresh. – fuggerjaki61 Feb 28 '20 at 15:47
  • @AdamWaldenberg the package is javax.faces.bean.ViewScoped – Joe Mar 02 '20 at 06:47
  • @Joe then it should work just fine. but do see the above bug I linked to ... some containers can sometimes behave incorrectly, causing `@PostConstruct` not to be called when you would expect. I have no idea about JBoss 5.2. – Adam Waldenberg Mar 02 '20 at 12:35
  • @AdamWaldenberg I found out more info about the question, because it happens when I redirect to other page, the postConstruct executes before the url is changed and when it changes the data are not available on the page. The commandBotton fixed/hacked the problem but it is not the way to proceed. – Joe Mar 04 '20 at 12:47
  • @Joe Yep. This behavior has since changed and we have moved on to CDI. 2.1.2 is almost 10 years old by now. – Adam Waldenberg Mar 05 '20 at 11:22

1 Answers1

0

This error seems to be a kind of bug and I did not found an explanation.

I just execute a hidden button from javascript in @PostConstruct managed bean.

It is not the way but it solved the problem with this patch.

PersonaBean.java

PrimeFaces.current().executeScript("document.getElementById(\"frmPersona:btnUpdate\").click()");

persona.xhtml

<p:commandButton id="btnUpdate" value="update" action="#{personaBean.doNothing}" process=":frmMenus" update=":frmMenus" style="display:none"/>

It looks like this bug in JSF:

Update (Dec 2012): this is indeed a bug in JSF2. It's a chicken-egg issue. The view scoped beans are stored in the JSF view state. So the view scoped beans are only available after restore view phase. However, the binding attribute runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state.

This is reported as JSF issue 1492 and JSF spec isssue 787 which will be fixed for JSF 2.2. Until then, your best bet is to use binding on request scoped beans exclusively, or to look for alternate ways for the particular functional requirement.

Balus has an article that deal with this issue or a very similar one.

Joe
  • 7,749
  • 19
  • 60
  • 110
  • 3
    Next time post a real [mcve] in order to get real answers, because your problem is not reproducible with information provided so far. Imagine us having a only a new completely empty project in the IDE with all defaults and latest versions and we are only able to adjust and/or copy paste the information provided so far. Try to do the same yourself. You'll see that you even can't reproduce yourself. – BalusC Mar 02 '20 at 12:37
  • 2
    This is more of a hack than a solution... But you might be right about it being a bug. You can solve it slightly cleaner with a `` as @BalusC suggested. But even then it's kind of a hack. Initializing your model in `@PostConstruct` should work perfectly fine and is really the correct way to do things. Doing what you are doing in this answer kind of makes the hair at the back of my neck stand straight up ;). – Adam Waldenberg Mar 02 '20 at 12:40
  • @BalusC thanks you I'll try to do a minimal example the next time – Joe Mar 03 '20 at 07:29
  • it WAS a bug? Since it says it will be fixed in JSF 2.2 (a link to the issue helps btw) – Kukeltje Mar 04 '20 at 12:56
  • @Kukeltje The link of the bug was broken, but I found a similar one on Balus web page https://balusc.omnifaces.org/2011/09/communication-in-jsf-20.html#ViewScopedFailsInTagHandlers – Joe Mar 04 '20 at 13:04
  • That is an almost 10 year old article... Can never be relevant to fixes in JSF 2.2 (might be for your version) – Kukeltje Mar 04 '20 at 13:33