I have problem with JSF (1.2) + primefaces (1.1). I have written classic site on JSF, and I have for every article request scoped backing bean. The problem is, that when I try to rate the article, the backing bean no longer exists.
So i want to force the JSF to output result of this expression during the render phase (so the ranking code will send the rendered Id), but if I use the dolar sign, everything works exacly as if I used the # (i thing that this might be bug in MyFaces).
Other solution wold be to session scope the backing bean, but user could have opened more pages (and he wold rate the last opened), other problem is what would happen, when the session expires....
Thanks for your help
<p:rating stars="5" value="#{articleClientBean.userRating}" update="ratingCount, avgRating" rateListener="#{articleClientBean.handleRate}">
<f:param value="#{articleClientBean.articleId}" name="articleId"/>
</p:rating>
Use h:inputHidden instead.
<p:rating stars="5" value="#{articleClientBean.userRating}" update="ratingCount, avgRating" rateListener="#{articleClientBean.handleRate}" />
<h:inputHidden value="#{articleClientBean.articleId}" />
Related
I have a backing bean (somebean) with three boolean properties a, b, and c, each has a getter and setter.
I have a form which looks like this:
<h:outputText rendered="#{somebean.b}">
B is true
</h:outputText>
<h:form id="blah">
<h:inputHidden value="#{somebean.a}" id="a"/>
<h:commandLink id="zzzz" value="do it" action="#{somebean.doIt}"/>
</h:form>
Which of the three properties a, b, and c can be set by the client? I tried adding b=true and c=true to the POST request, but SomeBean.setB(boolean) and SomeBean.setC(boolean) never get called. So perhaps only a can be set - the logic being that if there is a field in the JSF that sets it, the client is allowed to set it. But perhaps I'm wrong and it just has some default name that I don't know about that can be used to set it...
Should I just assume that any property on my bean can be set by the client? If not, which ones should I assume the client can set (and thus have to worry about during validation)?
Also what happens if I have my form conditionally rendered? e.g:
<h:outputText rendered="#{somebean.b}">
<h:form id="blah">
<h:inputHidden value="#{somebean.a}" id="a"/>
<h:commandLink id="zzzz" value="do it" action="#{somebean.doIt}"/>
</h:form>
</h:outputText>
In this case, can a still be set if b is false?
By "client", I mean anything sending HTTP traffic to my site. Which could be for example, malicious code.
Which properties in a JSF backing bean can be set by a user?
Those bound to an EditableValueHolder component, such as UIInput and friends (including <f:viewParam>!), with the precondition that they are rendered="true", disabled="false" and readonly="false" during apply request values phase.
Another possible way is through a #ManagedProperty("#{param.xxx}") on the property of a request scoped bean or a hardcoded ExternalContext#getRequestParameterMap() access in some bean method which is invoked during the HTTP request.
So, only when you as being the developer explicitly bind the property to an editable value holder component which is rendered, non-disabled/readonly, or when you as being the developer explicitly set a request parameter as a property. There are in the current releases of JSF implementations absolutely no security holes with reagard to the possibility of setting undeclared/unbound properties by HTTP means. It's even not possible to send an arbitrary value to a UISelectOne or UISelectMany component by spoofing the HTTP request, it would only end up in "Validation Error: Value is not valid".
As to security holes in older JSF implementations, only and only when you're navigating to a different view using includeViewParams="true" in a Mojarra version older than 2.0.7 and 2.1.5, then all EL expressions in view params such as #{bean.setArbitraryProperty('foo')} will be evaluated. See also issue 2247. I'm not aware of any security holes in MyFaces; that's not because there are none per se, but simply because I don't use/track it closely.
Is there a way to have a JSF Backing bean cause an update of a component on the page? I am not looking to use an ajax component with update attribute to update a component on the page. I need to trigger an update from within a JSF backing bean method. Note the update on the page can happen after this method completes or prior to its completion. I am using PrimeFaces, if there is a solution that can be had from using PrimeFaces.
Using standard JSF API, add the client ID to PartialViewContext#getRenderIds().
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add("foo:bar");
Using PrimeFaces specific API, use PrimeFaces.Ajax#update().
PrimeFaces.current().ajax().update("foo:bar");
Or if you're not on PrimeFaces 6.2+ yet, use RequestContext#update().
RequestContext.getCurrentInstance().update("foo:bar");
If you happen to use JSF utility library OmniFaces, use Ajax#update().
Ajax.update("foo:bar");
Regardless of the way, note that those client IDs should represent absolute client IDs which are not prefixed with the NamingContainer separator character like as you would do from the view side on.
I also tried to update a component from a jsf backing bean/class
You need to do the following after manipulating the UI component:
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(componentToBeRerendered.getClientId())
It is important to use the clientId instead of the (server-side) componentId!!
The RequestContext is deprecated from Primefaces 6.2. From this version use the following:
if (componentID != null && PrimeFaces.current().isAjaxRequest()) {
PrimeFaces.current().ajax().update(componentID);
}
And to execute javascript from the backbean use this way:
PrimeFaces.current().executeScript(jsCommand);
Reference:
https://github.com/primefaces/primefaces/wiki/Migration-Guide
https://forum.primefaces.org/viewtopic.php?t=53129
Everything is possible only if there is enough time to research :)
What I got to do is like having people that I iterate into a ui:repeat and display names and other fields in inputs. But one of fields was singleSelect - A and depending on it value update another input - B.
even ui:repeat do not have id I put and it appeared in the DOM tree
<ui:repeat id="peopleRepeat"
value="#{myBean.people}"
var="person" varStatus="status">
Than the ids in the html were something like:
myForm:peopleRepeat:0:personType
myForm:peopleRepeat:1:personType
Than in the view I got one method like:
<p:ajax event="change"
listener="#{myBean.onPersonTypeChange(person, status.index)}"/>
And its implementation was in the bean like:
String componentId = "myForm:peopleRepeat" + idx + "personType";
PrimeFaces.current().ajax().update(componentId);
So this way I updated the element from the bean with no issues. PF version 6.2
Good luck and happy coding :)
In order to updte the component from backing bean, we can achieve as below
RequestContext.getCurrentInstance().update('updatePanelGroup');
<h:panelGroup id="updatePanelGroup">
.....
....
</h:panelGroup>
Updating the component differs with respect to prima face version.
Sorry, really really basic question...
I've got a list of 'messageboard threads' that I display on a page. I want to be able to click on one of them and redirect to a page which displays the details for that thread. I'm struggling despite googling it for a while...
(I'm using PrimeFaces by the way)
Here's the relevant code from my 'list' page:
<p:commandLink value="#{thread.title}" action="#{messageboardBean.showThread()}">
<f:param name="threadId" value="#{thread.id}" />
</p:commandLink>
(it's in an h:form element)
This is part of my named bean (other methods work fine)
...
#ManagedProperty(value="#{param.threadId}")
private Long threadId;
...
public String showThread() {
System.out.println("id is " + getThreadId());
return "messageboard/list";
}
...
As you can see my method isn't implemented yet, but it's not even being called. Please can someone tell me why?
I tried with an h:link too by the way, same (or similar) problem.
Thanks!
UPDATE - Solved
Thanks to the help below, here is my solution (I've renamed 'messageboard' to 'discussion').
The link is generated using this code
value: what to display on the page, in my case the title of my discussion
outcome: refers to edit.xhtml, the faces file I want to go to
...and the [request] param is going to be called 'threadId' and has a value of the id attribute in my 'thread' object.
In the edit.xhtml page, I've got this
<f:metadata>
<f:viewParam name="threadId" value="#{viewDiscussionBean.threadId}" />
<f:event type="preRenderView" listener="#{viewDiscussionBean.loadDiscussion}" />
</f:metadata>
Note that 'threadId' is the same as the param name in the first page, and it is bound to my viewDiscussionBean's threadId property.
Then once the params are all set on my bean, I call the loadDiscussion method of my viewDiscussionBean. Since it now has the threadId property, it's able to do this (see below)
My viewDiscussionBean has the following managed property (I think the viewParam tag sets this, rather than the other way around).
#ManagedProperty(value="#{param.threadId}")
private Long threadId;
private Discussion thread;
So once that's set, this method is able to run (because it now has an ID)
public String loadDiscussion() {
thread = mbDao.find(threadId);
return "edit";
}
This just uses a DAO (using Hibernate) to look up the discussion thread with that ID, and set it in the bean. And then...
In my edit.xhtml page, I can access values in the discussion thread using things like
<h:outputText value="#{viewDiscussionBean.thread.message}" />
Voila! Thanks.
There are many possible caused for an UICommand action not being invoked. You can find them all here: commandButton/commandLink/ajax action/listener method not invoked or input value not updated Among others a missing form, a nested form, or a conversion/validation error elsewhere in the form, being in a datatable whose datamodel is not properly preserved, etcetera.
As to your particular functional requirement, better is to use a <h:link>. A command link issues a POST request which does in your particular case not end up with a bookmarkable URL with the thread ID in the URL. A <h:link> creates a fullworthy link which is bookmarkable and searchbot-indexable.
E.g.
<h:link value="#{thread.title}" outcome="messageboard/list">
<f:param name="threadId" value="#{thread.id}" />
</h:link>
This doesn't require a form nor an action method. You only need to move that #ManagedProperty to the bean associated with messageboard/list, or maybe replace it by <f:viewParam> in the messageboard/list view which allows for finer-grained validation/conversion.
See also:
Communication in JSF2 - Processing GET request parameters
When should I use h:outputLink instead of h:commandLink?
ViewParam vs #ManagedProperty(value = "#{param.id}")
Your best bet it probably to go with BalusC's answer and use <h:link>. However, I have some thoughts about the behavior you're seeing.
Primefaces <p:commandLink> (like <p:commandButton>) uses ajax by default. Therefore, there won't be any actual navigation resulting from returning an outcome from your action. This could make it look like your action isn't being invoked. Try adding ajax=false to your <p:commandLink>.
When using <h:link>, navigation is resolved when the link is rendered rather than when it's clicked. Modifying your example:
<h:link value="#{thread.title}" outcome="#{messageboardBean.showThread()}">
<f:param name="threadId" value="#{thread.id}" />
</h:link>
showThread() will be called (I think) when the view containing the link is being rendered. If you're not checking at the right time, this may also make it look like the method is being called.
In both cases, this doesn't explain why you wouldn't see the message to System.out at all, but I know I've tried that thinking it was fail-safe and still not seen the output, which all depends on your container, configuration, how you launched it, etc.
My web application has two search pages - search1.jsf and search2.jsf - which share the same bean which in turn calls a result page - result.jsf.
So both search pages have a commandButton
<h:commandButton value="Commit" action="#{search.commit}" />
The "search" bean then processes the search and forwards to the result page using
target = "result?faces-redirect=true";
Now the result.jsf doesn't know which search page has been used. How can I pass the calling page so that the called page is able to render a link back to the calling page?
Using the browser back button (or Javascript code) to go back in the history has the disadvantage that the user, after browsing through the results, only would go back one page in the results instead of going 'up' to the search parameter form.
Options I see so far are:
pass the caller page name through the chain to the result page, using <f:param> or action="#{search.commit(name_of_calling_page)}
put all 'search parameter' forms in one JSF page and conditionally switch the content
Or is there a JSF functions which returns the name of the calling JSF page?
You're redirecting to the result page which suggests that you're using a session scoped bean to hold the results (a request/view scoped simply doesn't survive redirects). Ignoring the fact that this is a poor/odd approach, you could just store the search type in that bean as well?
Anyway, easiest and cleanest is to use a single master view with a single master view scoped bean and conditionally display search1.xhtml, search2.xhtml and results.xhtml using <ui:include> in the master view.
search.xhtml
<ui:fragment rendered="#{empty search.results}">
<ui:include src="/WEB-INF/search#{search.type}.xhtml" />
</ui:fragment>
<ui:fragment rendered="#{not empty search.results}">
<ui:include src="/WEB-INF/results.xhtml" />
</ui:fragment>
As long as you return void or null in action methods, the same view scoped bean will be retained on every subsequent (and non-redirected!) request. If you intend to make it a GET instead of POST (so that it's bookmarkable and back-button-navigable such as Google), then you should actually change the forms and view parameters to make it GET instead of POST.
I would like to basically do what Jason asked for here
In one sentence, I would like the url bar to represent the state of the AJAX application so that I can allow to bookmark it as well as allow the user to return to the previous state by using the back/forward buttons in the browser.
The difference for me (From what Jason asked) is that I am using JSF 2.0.
I've read that JSF 2.0 added the ability to use get, but I am not sure what the correct way to use this.
Thanks for the help.
Further Clarification
If I understand correctly, to be able to bookmark specific states in the AJAX webapp I will have to use the location.hash. Am I correct? I'm trying to achieve a gmail-like behaviour in the sense that, while the app is complete AJAXified and no redirects occur, I can still use Back/Forward and bookmark (And that's why I would like the URL bar to be updated from the AJAX app itself and not through redirection)
Update
Just found this similar question
The difference for me (From what Jason asked) is that I am using JSF 2.0. I've read that JSF 2.0 added the ability to use get, but I am not sure what the correct way to use this.
Please note that this is not the same as maintaining the Ajax state. It usually happens by fragment identifiers (the part starting with # in URL, also known as hashbang). JSF doesn't offer builtin components/functionality for this. As far I have also not seen a component library which does that. You may however find this answer useful to get started with a homegrown hash fragment processor in JSF.
As to using GET requests, just use <h:link>, <h:outputLink> or even <a> to create GET links. You can supply request parameters in the h: components by <f:param>. E.g.
<h:link value="Edit product" outcome="product/edit">
<f:param name="id" value="#{product.id}" />
</h:link>
In the product/edit.xhtml page you can define parameters to set and actions to execute upon a GET request
<f:metadata>
<f:viewParam name="id" value="#{productEditor.id}" />
<f:event type="preRenderView" listener="#{productEditor.init}" />
</f:metadata>
In the request or view scoped bean associated with product/edit.xhtml page -in this example #{productEditor}-, you just define the properties and the listener method. The listener method will be executed after all properties are been gathered, converted, validated and updated in the model.
private Long id;
private Product product;
public void init() {
product = productService.find(id);
}
Normally you'd use AJAX to prevent complete page refreshes. AFAIK all current browsers would issue a page refresh if you change the base uri. Thus you would have to use the hash part as suggested in the question you provided.
We had a similar problem and did something like this:
We settled for the fact that users cannot bookmark the url.
For URLs that should be unique/bookmarkable we used different links that issue a redirect. Those URLs are provided in a sitemap.
For browser back, we added an intermediate page after login. This page does navigation and a redirect to the application. The navigation is stored in the session and when the server gets a navigation request (which can be a history back) the corresponding state is restored. A browser back opens that intermediate page which issues a redirect along with a navigation request on the server side.