f:viewParam and f:viewMethod not calling (jsf) - jsf

As I know <f:viewParam> we use for GET parameter.
Also I know <f:viewAction ...> we can use for acess check usually for each specific situation (for specific view/bean). As well as calls at the beginning. So I’ve done. Specifically I have a bean - ViewScopedBean myBean. And a view (.xhtml) which includes
<f:metadata>
<f:viewParam name="param" value="#{viewScopedBean.param}" />
<f:viewAction action="#{viewScopedBean.doCheck()}" />
</f:metadata>
But Setter and method are not call.
I use JSF 2.2.9.
And I try change namespaces xmlns.jcp.org and java.sun.com. But i’ve not received results.
Could you help me with this question? What should I check? What should I do for correct result?
Thanks a lot for you attention and help.

Related

Primefaces Dialog Framework and Parameters [duplicate]

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?
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:
ViewParam vs #ManagedProperty(value = "#{param.id}")
Communication in JSF 2.0 - Processing GET request parameters

Multiple <f:viewAction> in <f:metadata>

I am developing a CMS using JSF 2.3. I need to pass a GET parameter to every page indicating the site that the user is managing. To do this I am using <f:viewParam> in all pages, but I have the following doubts:
Is it OK to use multiple <f:viewAction> for multiple managed beans like the following example?
<f:metadata>
<f:viewParam name="form" value="#{editFormWebBean.formIdParam}"/>
<f:viewParam name="site" value="#{headerWebBean.siteIdParam}"/>
<f:viewAction action="#{editFormWebBean.init}" />
<f:viewAction action="#{headerWebBean.init}" />
</f:metadata>
This works, but I am not sure if it is OK.
Is there a way to avoid replicating in every page the <f:viewParam> for the site parameter? I tried with includeViewParams, but doesn't worked if I don't include the <f:viewParam> in the source and destination page (from page1.xhtml to page2.xhtml)
3) Can I define multiple <f:metadata> tags? For example if I am using templates and multiple ManagedBeans pare page (one for the header, one for the menu and so on).
Thank you and sorry about my english.
it's okay to have as many <f:viewParam> and <f:viewAction> as long as they work well together, but please make sure these are meant to initialize the view "JSF page" not the backing beans, use #PostConstruct on the baking beans to initialize them, also but in your mind that <f:viewAction> is only executed on GET request by default any subsequent POST (postback) requests don't invoke the action unless it has onPostBack="true" attribute.
more on these tags can be found in this great answer
[What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?][1]
put it in a template using the templating feature of JSF like this:
template.xhtml
<f:metadata>
<f:viewParam name="site" value="#{headerWebBean.siteIdParam}"/>
<ui:insert name="metadata"/>
</f:metadata>
page.xhtml
<ui:composition template="template.xhtml">
<ui:define name="metadata">
<!-- whatever metadata you want to add-->
</ui:define>
</ui:comosition>
no it's one metadata tag per page, use it like the example above.
[1]: https://stackoverflow.com/a/6377957/4649524

How to call the same method after every include of a .xhtml page in JSF?

I have the following part of a .xhtml page:
<ui:composition template="./templates/template.xhtml">
<ui:define name="mainContent">
<ui:include src="include/includeAbleEditor.xhtml">
<ui:param name="includeParam" value="MyClass" />
</ui:include>
<ui:include src="include/includeAbleEditor.xhtml">
<ui:param name="includeParam" value="YourClass" />
</ui:include>
</ui:define>
In the "includeAbleEditor.xhtml" I want to call a method after it was included (In this case this should happend two times).
Now I tried to solve it like this: (metadata tag is part of the includeAbleEditor.xhtml)
<f:metadata>
<f:event type="preRenderView" listener="#{editor.onload}" />
<f:attribute name="textFieldId" value="#{includeParam}" />
</f:metadata>
The Problem:
The method is being called only once. But it should be called two times. Once with the parameter "MyClass" and once with "YourClass".
Do you have any suggestions?
Thanks a lot!
There can be only one <f:metadata> in the entire view and it must be in the top level view. Unlike e.g. <f:view>, they don't "extend" each other and all others will be ignored.
You actually don't need it here. It's only necessary whenever you need to attach <f:viewParam> and/or <f:viewAction> to the specific view. The <f:event> doesn't require a <f:metadata>. It will just be hooked to the parent UIComponent. It was during JSF 2.0/2.1 ages (when <f:viewAction> didn't exist) being abused to have a hook to invoke a listener after <f:viewParam> values are being set. It's just for self-documentary purposes being placed in the same <f:metadata> as where all <f:viewParam>s are.
So, just get rid of it.
<f:event type="preRenderView" listener="#{editor.onload(includeParam)}" />
That said, postAddToView is likely a better event to hook this all on. And to avoid "Duplicate component ID" errors over all place later on, consider wrapping it in <f:subview> or making it a composite.
See also:
When using <ui:composition> templating, where should I declare the <f:metadata>?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Avoiding duplicate ids when reusing facelets compositions in the same naming container

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>.

View parameters in different beans

I've got a page called trip.xhtml where I take parameters out of the URL using the following code:
<f:metadata>
<f:viewParam name="tripid" value="#{tripBean.tripId}" />
<f:viewParam name="seats" value="#{tripBean.seats}" />
<f:event type="preRenderView" listener="#{tripBean.processParams}" />
</f:metadata>
The TripBean looks like this (simplified):
#ManagedBean
#RequestScoped
public class TripBean implements Serializable {
private static final long serialVersionUID = -4885781058258859229L;
private Long tripId;
private int seats;
// Getters and setters for tripId and seats
On the bottom of the trip.xhtml page I have a h:link:
<h:link outcome="/customer/booking.xhtml" value="Book this trip"
includeViewParams="true" />
What I expect is that the URL I get when I click this link is something like "/customer/booking.jsf?tripid=2&seats=1". This is only the case when I put the following code on my booking.xhtml page:
<f:metadata>
<f:viewParam name="tripid" value="#{tripBean.tripId}" />
<f:viewParam name="seats" value="#{tripBean.seats}" />
</f:metadata>
Although what I actually want is to use another bean. Changing the code to:
<f:metadata>
<f:viewParam name="tripid" value="#{bookingBean.tripId}" />
<f:viewParam name="seats" value="#{bookingBean.seats}" />
</f:metadata>
The BookingBean also has 2 properties tripId and seats which are identical to the TripBean, but when I try to click the link now, I only see a seats-parameter which is set to 0. ("/customer/booking.jsf?seats=0")
Does anyone have any idea why I can't seem to pass the viewparams to the other page when I'm trying to use another bean to store them in? And IF it is impossible to store it in another bean, how can I put those values from TripBean in BookingBean?
Quick work-around I used:
Not using includeViewParams="true" , but adding parameters to the link manually (see below) "fixes" the problem. Although I'm still wondering why it won't work with includeViewParams!
<h:link outcome="/customer/booking.xhtml" value="#{msg['page.trip.booking']}">
<f:param name="tripid" value="#{tripBean.tripId}" />
<f:param name="seats" value="#{tripBean.seats}" />
</h:link>
f:viewParam works exactly like h:inputText. This means that it uses the same expression as a source (when rendering) and as a target (when updating the model). If you had:
<h:inputText value="#{a.test}" />
You would never ask "how to make the inputText read from b.foo and write to a.test", yet everyone seems to expect such behavior from f:viewParam.
Anyway, there is a simple answer. To append any values to link, you just need to use f:param:
<h:link outcome="/customer/booking.xhtml" value="Book this trip" >
<f:param name="tripid" value="#{bookingBean.tripId}" />
<f:param name="seats" value="#{bookingBean.seats}" />
</h:link>
The link content corresponding to the following tag:
<h:link outcome="/customer/booking.xhtml" value="Book this trip"
includeViewParams="true" />
is generated during the render-response phase of the request for the trip.xhtml view. If you need the URL to contain the view parameter values, then you must provide these values in the URL used to access the view, or you must set these values in the model, before the render-response phase is complete. If you do not perform either of these, the generated hyperlink will contain the default values for the view parameters.
In simpler words, you must:
either ensure that the trip.xhtml view is accessed with the necessary parameters: trip.xhtml?tripid=x&seats=y, especially if the view is to be accessed with parameters at all times.
or you must set the values in a method that gets executed before the link is rendered by the JSF runtime. The constructor of the BookingBean class or a #PostConstruct annotated method in the class would be ideal places to set the values. You could also reset/update the values of the bean in other methods of your managed bean, in the event of actions being performed in the view. Note, that JSF runtime will invoke getTripId and getSeats to include the values of the view parameters tripId and seats in the resulting URL, so you ought to verify the behavior of these methods as well.
Your question on why you are unable to specify bookingBean in the EL expression for booking.xhtml, instead requiring you to specify the supposedly unexpected value of tripBean is due to the fact that the includeViewParams attribute of the link tag, will include the parameters of the to-view and not the from-view. Simply put, the JSF runtime will invoke bookingBean.getTripId() and bookingBean.getSeats() and not tripBean.getTripId() and tripBean.getSeats().
While this might seem counter-intuitive, you ought to understand that the JSF specification treats this scenario quite differently. In most interactions performed by a user, the action URL of a component is generated when the user performs the action and not until then. The link tag on the other hand, requires preemptive computation of the URL, and hence the JSF runtime treats this quite differently as "pre-emptive navigation". When the URL is being constructed, the objects pertaining to the view parameters of the target view must be accessible, in order for the URL to be meaningful. The reason for the values being 0 in the URL, is that a new BookingBean instance is created during this evaluation and the default values are being used instead. You can quite obviously avoid this by using the TripBean instead (and most examples of includeViewParams demonstrate this), or you can set values during the construction of the BookingBean object.

Resources