Execute managedBean method only for a specific page - jsf

For a page, I need to initialize potentially a huge list of object.
For now, I populate this list in a #PostConstruct method
Is it possible to execute a method only on a specific page?
Or is there a JSF tag to simply execute a method and nothing more ?
It's not an important issue for me but there must be a solution.
I'm using JSF 2.

You may add this to your page:
<f:event type="preRenderView" listener="#{backingBean.desiredMethod()}" />
This will execute the desiredMethod() before the RenderView lifecycle phase.

Related

How to execute a bean method inside foreach without button or link in jsf?

I am looping a list containing strings in foreach, so in every iteration the variable in foreach loop should be passed as a parameter to a bean method written inside the foreach loop. I searched many sites but everywhere I am finding solution that bean method cannot be executed without commandbutton or link. Is there any solution to execute bean method without any commandbutton or link.
<c:forEach var="name" items="#{bean.stringList}"
varStatus="loopCounter">
<!--I have to execute the method here passing "name" as parameter-->
</c:forEach>
Since EL 2.2 you can invoke non-getter methods with arguments. So you could use:
<c:forEach var="name" items="#{bean.stringList}"
varStatus="loopCounter">
<c:set var="dummy" value="#{bean.yourMethod(name)}" />
</c:forEach>
However, you are most likely are trying to solve something here that can be done in more elegant ways like a PhaseListener, a #PostConstruct method, a f:viewAction, etc.
See also
How to implement a PhaseListener which runs at end of lifecycle?
Why use #PostConstruct?
When to use f:viewAction / preRenderView versus PostConstruct?

Using <h:button> <h:link> with Manage Beans

When i use
<h:button>
or
<h:link>
i can't make any business action in managed bean ?
Do I have to use
<h:form>
and
<h:commandButton>
or
<h:commandLink>
with action param or there is another solution ?
Depends on the kind of request you'd like to fire.
If it needs to be a non-idempotent POST request, just use <h:form> with <h:commandXxx action>. Again depending on the concrete functional requirement, you can render the results conditionally in the same view, or send a redirect to the target view afterwards.
If it needs to be an idempotent GET request, use <h:link>/<h:button> and perform the action in #PostConstruct method in the request/view scoped backing bean associated with the target page. If you need to pass parameters, use <f:param> to set them on <h:link>/<h:button> and use <f:viewParam> and <f:event type="preRenderView"> in target view to set and process them in backing bean associated with target view.
All in all, just use the right tool for the job as specified by concrete functional requirement (which you unfortunately didn't tell anything about in your question).
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Communication in JSF 2.0
No, you can't do that with h:link or h:button, there are meant to be bookmarkable GET urls. So if you want to perform business action, you need to use either commandButton or commandLink. Note that it's also worth to use h:outputLink for generating bookmarkable links between pages because is much more SEO friendly.

jsf navigation to another method

I am developing an application using jsf 2.0 and i have the following situation:
I have 2 managed beans.
On the first managed bean i have a method that process some data and then store the result in session.After the data was stored in session i need to invoke a method on the second bean that will display the information from session.
The problem is that if i return a string from the first bean method that correspond to the seconds bean method view the data is not processed, and of course not displayed.
What i need is some navigation rule that from the first bean would redirect me to the second bean method, and the second bean method would return a string with the corresponding view name.
update
maybe a
<f:event listener="#{secondBean.methodToBeInvoked}" type="preRenderView" />
would help me achieve that.
Is this the right approach ?

Does it matter whether place f:event inside f:metadata or not?

w.r.t. How to execute action on GET request with f:viewParam?
<f:metadata>
<f:viewParam name="id" value="#{tInputBean.id}" />
<f:event type="preRenderView" listener="#{tInputBean.init}" />
</f:metadata>
I'm interested to know whether it matters if a preRenderView f:event is placed inside the f:metadata or not. I've checked the Java EE6 tutorial, Java Server Faces 2.0 Complete Reference, and Core JSF2, and none of them have examples of f:event inside f:metadata, but I've seen lots of examples online like this.
JSF2 Compl.Ref says p.540
The f:metadata tag encapsulates the set of elements used to specify
the metadata for a Facelet view, and therefore must be a child of the
f:view tag and may not appear in a template. As of JSF2.0, the only
purpose of this tag is to encapsulate f:viewParam tags.
Does placing the f:event (often used to support an f:viewParam) inside the f:metadata have a special meaning, or is it just to help group it alongside the f:viewParam visually/logically ?
No, the <f:event> is not strictly required to be placed inside <f:metadata>. It can be attached to any component. It's indeed for pure self-documentary purposes placed inside the <f:metadata> whenever you have a bunch of <f:viewParam>s and would like to hook a <f:event> to invoke an action after all those view parameters have been set. It can even be placed outside/before those <f:viewParam>s, but it makes the code not more self-documenting.
Note that in the upcoming JSF 2.2, a new <f:viewAction> tag will be introduced which in turn is supposed to replace the <f:event type="preRenderView"> in the <f:metadata>.

JSF 2 : Accessing managed bean's instance in the phase listener object?

Is it possible to get a reference to the to-be-executed managedbean in the before-invokeApplication-phaselistener ?
Before the invoke application phase, it should be clear which managedBean that is going to execute the method.
For the sake of the example, assume there's 1 main manage bean to handle 1 jsf page.
So what i need is basically :
The user access the program from the menu
Because it's accessed from the menu, the main manage bean's init() method gets called to initialize stuffs like preparing data, doing authorization checks
Subsequent submits dont need to call the init() method anymore until it's reaccessed from the menu
To implement the point #2, im thinking of intercepting one of the phases
I've checked the API docs about getting the managed bean in the phases implementation, but i couldnt seem to find any.
After typing this question, i realize i could do this in #PostConstruct or the managed bean's constructor, but that would do only at the first time the bean is constructed, and my need is to call the method everytime the jsf is being accessed from the menu.
Any suggestions ?
Regards,
Albert Kam
You can access your managed beans via the ELContext/ELResolver. This is explained nicely in the MyFaces wiki (also works in vanilla JSF).
For example:
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
NeededBean neededBean = (NeededBean) FacesContext.getCurrentInstance().getApplication()
.getELResolver().getValue(elContext, null, "neededBean");
See the MyFaces wiki entry for further explanation, and implementations for other JSF versions.
Your idea of using #PostConstruct is a good one. Consider changing your scope to something liked #ViewScoped, so the logic is executed everytime you navigate to that view.
Also, have a look at the PreRenderViewEvent (for JSF 2). This code is embedded in your facelet page:
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}"/>
<f:event type="preRenderView" listener="#{bean.doSomething}"/>
</f:metadata>
The f:event listener is executed before every page view.

Resources