JSF bean: call @PostConstruct function after ViewParam is set
Asked Answered
C

1

12

I have a product.xhtml and a ProductBean. I use /product/{id} to access the products so I have a viewParam in product.xhtml with value=ProductBean.id. The problem is that inside the bean I use an init function with a PostConstruct annotation in order to fill the details of the product. To do this I need the id to call an external function. I guess though that init is called before viewParam sets the id of the bean and therefore inside init I cannot call the external function because id is not set yet. What am I doing wrong and how do I fix this?

UPDATE

I found what was wrong. I think the viewParam method works with CDI beans but the ManagedProperty method works with JSF beans..

I do have one other problem now. My CDI bean is RequestScoped and when the product.xhtml is rendered the bean is created and I guess is later discarded. The funny thing is that I have a function inside that bean which when I call, I can read the id (which I assume this happens because is connected to the view param) but not any other properties. Any ideas how to fix this?

Continuity answered 21/4, 2012 at 17:44 Comment(1)
As to your update, your statement about viewParam is wrong. The <f:viewParam> is not specific to CDI. This works regardless of who's managing the bean. The @ManagedProperty indeed works in JSF @ManagedBean only, but that's not more than obvious as @ManagedProperty is a JSF-specific annotation, not a CDI-specific annotation.Brozak
B
27

You need a <f:event type="preRenderView"> instead.

<f:metadata>
    <f:viewParam name="foo" value="#{bean.foo}" />
    <f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>

With

public void onload() {
    // ...
}

Note that this is in essence a little hack. The upcoming JSF 2.2 will offer a new and more sensible tag for the sole purpose: the <f:viewAction>.

<f:metadata>
    <f:viewParam name="foo" value="#{bean.foo}" />
    <f:viewAction action="#{bean.onload}" />
</f:metadata>

See also:

Brozak answered 21/4, 2012 at 17:58 Comment(8)
I added what you suggested but I still cannot read the id inside initContinuity
I couldn't make it work with the first method in the first link you posted but I could make it work with the second one. I understood though that the first method is better than the second, is this correct?Continuity
Hard to say without seeing some concrete code. I'd bet that you was doing something wrong.Brozak
Is the idea here to skip @PostConstruct annotation completely and rely on init called from preRenderView?Porush
By me is f:event called also on postback, I had to add flag if the initialization is already done, is it possible to call that event exactly once, such as with @PostConstruct?Transfinite
@Brozak hmm one thing have striked me now as I'm making design for complicated structure, I want to parcel the complex structure among multiple beans, I've planned to have one bean reading data (initialized by this view action), and others having it as managed property, reading the portions of data. But since they will get that bean after its PostConstruct, they will have their PostConstruct called before those viewAction will execute, am I right?Transfinite
but preRender is called on every request (postback ajax or normal postaback). So you suggest to re-initialize your bean on every request ? Problem is JSF Managed Beans and CDI beans are two different worlds (containers) brought together. They can coexists, but code is full of hacks. I doubt any new version of JSF or CDI will fix things because mixing two different component models is always dirty job.Pavier
@MitjaGustin: Indeed, see also #6378298 OP has however a request scoped bean, not a view scoped bean. So those additional checks are not necessary. Just upgrade to JSF 2.2 and grab <f:viewAction>.Brozak

© 2022 - 2024 — McMap. All rights reserved.