How does JSF load property values of managed bean? - jsf

I am a JSF beginner. I have a question about managed bean.
Step 0:
There is a managed bean BeanA, scope is request. And BeanA instance1.propertyA = "0";
Step 1:
using ajax to change country, then in BeanA.countryChanged method, change managed bean BeanA.propertyA = "A".
<t:selectOneMenu id="Country" required="true" valueChangeListener="#{BeanA.countryChanged}">
<a4j:support event="onchange" limitToList="true" ajaxSingle="true" />
<f:selectItems value="#{BeanA.countries}" />
</t:selectOneMenu>
Step2:
submit form to do validate a text input
<h:inputText id="street" required="#{BeanA.propertyA == "A"}"
I expect that in step2 the value propertyA of BeanA instance2 should be "A" in JSF validate phase, but actually it is "0". I don't know how does JSF load BeanA instance property values to create new BeanA instance. And what should I do, the value will changed to "A"? Thanks,

The symptoms indicate that your bean is request scoped. This means that it's reconstructed on every single HTTP request. You probably didn't realize that every single ajax request also counts as a separate HTTP request. In effects, you're not reusing the same bean instance across ajax postbacks on the same view. Every time a brand new instance is been created, with all its properties set to default.
JSF 2.0, which is designed with ajax in mind, has solved it with the new view scope in the standard API.
In JSF 1.x, you need to fall back to 3rd party component libraries. In your particular case, given that you're using both Tomahawk and Ajax4jsf, you've 2 options:
Use <t:saveState>.
<t:saveState value="#{BeanA}" />
Or, use <a4j:keepAlive>.
<a4j:keepAlive beanName="BeanA" />

Related

One <p:dialog> for multiple beans

I have a <p:dialog> in my general layout. I have its Header attribute hardcoded at the moment.
What I want is to access it from different beans and change its Header at run-time according to my choice.
I am using it to show a loading message to the user at the moment and want to update the loading text according to the current backend processing, e.g "waiting for server's response" etc.
<p:dialog id="main-status-dialog"
widgetVar="mainStatusDialog"
modal="true"
header="Loading..."
draggable="false"
closable="false"
resizable="false"
appendToBody="true">
Now I am calling it from different JSF pages on button clicks e.g <h:link outcome="/generalInformation" value="General Information" onclick="mainStatusDialog.show()" />
It works fine but always Show me "Loading..." because I have a hardcoaded Attribute. So how can I make it dynamic? Please note that I don't want to do it only for one page or bean, but from any page it Access it, i can Change ist Header accordingly.
Thanks!
You can use a managed property with #ManagedProperty of one of your managed beans (e.g HeaderBean)and change it every time accordingly and set the header value to this value, and it whould look dynamically updated.
#ManagedProperty("#{headerBean}")
private HeaderBean headerBean;
And in your header managed bean make a String property value where you will store the value of the header:
#ManagedBean(name = "headerBean")
#RequestScoped
public class HeaderBean implements Serializable
{
private String value = null;
// getter and setter methods
And in your p:dialog:
<p:dialog id="main-status-dialog"
widgetVar="mainStatusDialog"
modal="true"
header="#{headerBean.value}"
draggable="false"
closable="false"
resizable="false"
appendToBody="true">
Take a look at the following liks to find more about it:
The BalusC Code: Communication in JSF 2.0
Injecting Managed beans in JSF 2.0
#ManagedProperty - Inject one request scoped bean into another request scoped bean
EDIT:
You can use RequestContext to update the dialog from your beans, If you take a look at Better ajax operations and callbacks in JSF with PrimeFaces you will see that:
RequestContext API enables developers to do 2 simple things. 1st you can tell what you want to update in the xhtml based on conditions in actions that you define in your Managed Beans.To update a component from serverside, you can just write:
The code you need to update the p:dialog from your managed beans is:
RequestContext.getCurrentInstance().
addPartialUpdateTarget("header_id");
You can also use update attribute in your commandLink like this:
<h:link outcome="/generalInformation" value="General Information" oncomplete="mainStatusDialog.show()" update=":main-status-dialog"/>

How to update value of EditableValueHolder in action listener?

I have this JSF (Java EE 7, provided by GlassFish 4.1 + PrimeFaces 5.1) form containing database connection information like host name, port number, etc. Also part of this form is a URL field. I want this field to be editable, but I also want to be able to set the value based on the other fields.
To do so I created a button with an action listener where I'm reading the posted data from the request parameter map and generate the new URL value. Then I want to put the new value in the URL field and use that value instead of the posted data. What I tried is to get the component as EditableValueHolder and set the submitted value and render the response. I also tried setting the component's value and calling resetValue.
The best result was the URL field being updates after two clicks.
XHTML:
<p:inputText id="url"
size="50"
value="#{database.url}"/>
<p:commandButton icon="ui-icon-arrowrefresh-1-w"
immediate="true"
actionListener="#{database.createConnectionURL('namingContainer')}">
<p:ajax update="url" />
</p:commandButton>
Bean (using OmniFaces):
UIComponent urlComponent = Faces.getViewRoot().findComponent(namingContainer + "url");
if (urlComponent instanceof EditableValueHolder) {
EditableValueHolder editValHolder = (EditableValueHolder) urlComponent;
editValHolder.setSubmittedValue(urlValue);
}
Faces.getContext().renderResponse();
The immediate="true" is a leftover from JSF 1.x, when it was not possible to process only a specific set of inputs and/or buttons. It was then more than often abused to process only a specific set of inputs and/or buttons instead of to prioritize validation. You'd better not use it when you've JSF2 ajax at hands.
With JSF2 ajax you can just use execute="..." or in case of PrimeFaces process="..." to execute/process only a specific set of inputs/buttons.
<p:inputText id="url"
size="50"
value="#{database.url}" />
<p:commandButton icon="ui-icon-arrowrefresh-1-w"
process="#this"
action="#{database.createConnectionURL('namingContainer')}"
update="url" />
Then you can just update the model value.
public void createConnectionURL(String namingContainer) {
// ...
url = urlValue;
}
Note that I moved back <p:ajax update> into the <p:commandButton>. Perhaps you was mixing with <h:commandButton>.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
Unrelated to the concrete problem, to deal with components with OmniFaces, better use Components utility class.

valueChangeListener isn't always triggered depending on the rendered attribute

I'm having trouble to understand why valueChangeListener isn't triggered.
I came accross this topic valueChangeListener Not fired when rendered/disabled attribute is added
but it didn't help so much.
When my xhtml is this :
<h:inputText value="#{cm.reference}"
rendered="#{cm.endDate eq null}"
valueChangeListener="#{userDataBean.ContactMethodChanged}" />
it's working (I mean the valueChangeListener is triggered)
But when I try this :
<h:inputText value="#{cm.reference}"
rendered="#{cm.contactMethodId eq param.contactMethodID}"
valueChangeListener="#{userDataBean.ContactMethodChanged}" />
it doesn't.
Unfortunately I need to have the second option working.
More info :
I'm inside a h:dataTable where I iterate on a list of ContactMethod (cm)
UserDataBean is applicationScoped
Apache Tomcat 7.0
JSF 2.2 (Mojarra 2.2.0)
Thank you for any help.
If the input is not processed during the form submit, then that can only mean that the rendered attribute didn't evaluate true during processing the form submit, which in turn can only mean that the #{cm.contactMethodId} has incompatibly changed (e.g. because it's a request scoped bean property instead of a view scoped bean property) and/or that #{param.contactMethodID} isn't present during the form submit.
Provided that the bean is in the right scope for the job (otherwise the original rendered approach would likely not have worked either), then retaining the request parameter as follows in the command button/link responsible for submitting the form should do it:
<h:commandButton ...>
<f:param name="contactMethodID" value="#{param.contactMethodID}" />
</h:commandButton>

How to get p:inputText value and set it as f:param value?

I have an xhtml page as follows
<p:inputText id="inputFilterKey" name="inputFilterKey" value="#{key}" />
<p:commandButton id="filterByKey" action="searchByKey" value="Search" ajax="false">
<f:param name="filterKey" value=? />
</p:commandButton>
The parameter 'filterKey' should have the value which is provided by user in the inputText. Value '#{key}' is the flow scope variable which is defined in spring webflow. That is, it is not taken from a back bean. How should I get the value of the inputText? Here is the flow definition in case it is need.
<transition on="searchByKey" to="editTexts" >
<set name="flowScope.key" value="requestParameters.filterKey"/>
<evaluate expression="textManager.searchByKey(key)" result="viewScope.textsByKey" result-type="dataModel"/>
</transition>
Thanks
That isn't possible. The <f:param value> is evaluated when the form is rendered/displayed, not when the form is submitted/processed.
I'm not familiar with Spring Webflow, but this is IMO a really strange design. You might want to confirm with the SWF guys if you're doing things the right way. Perhaps you should rather inject the SWF variable as a managed bean property during its construction/initialization or something?
Anyway, there are ways to get the submitted value without binding the input component's value to a managed bean property. One of them is just getting it straight from the request parameter map by #ManagedProperty:
#ManagedProperty("#{param['formId:inputFilterKey']}")
private String key; // +setter
or when the managed bean has a broader scope than the request scope:
String key = externalContext.getRequestParameterMap().get("formId:inputFilterKey");
The formId:inputFilterKey is just the name of the generated HTML <input> element representation of the <p:inputText> component.

What is the JSF behaviour, if you bind the same backing bean property to two input fields in the same form?

Is there a defined behaviour in JSF, if two input fields are bound to the same session scoped Backing Bean property.
Here is my code snippet
<h:form id="myForm">
<h:inputText id="field1" value="#{TheBackingBean.theProperty}" />
<h:inputText id="field2" value="#{TheBackingBean.theProperty}" />
<h:commandButton id="continueButton" action="#{TheBackingBean.doSomething}" />
</h:form>
My question: If field1 and field2 receive different values, what will be bound to the backing bean property? Is this even allowed?
I know this is a crude scenario. My motivation is, that we have htmlunit tests running for our application. In our JSF application we want to use a cool ajaxified custom component. This doesnt work together very well with htmlunit. So my idea was, I just put in a hidden field that binds to the same property. The unit test then fills the hidden field instead of the "real" thing.
Regards
I think this kind of code is allowed, but I am not sure of the value of theProperty after the submission. What I think is that JSF will do the following:
TheBackingBean.setTheProperty(field1.value);
TheBackingBean.setTheProperty(field2.value);
However, nothing - as far as I know - specifies the order of the setter calls. Thus, after the update values JSF phase, you will not be sure if theProperty will be equal to field1.value or field2.value.
Concerning your scenario, you say that you want to bind the same property to an inputText and an hiddenText. As the hiddenText will not submit its value, unlike the inputText, this problem will not occur. Indeed, if you have this kind of JSF code:
<h:inputText id="field1" value="#{TheBackingBean.theProperty}"/>
<h:inputHidden id="field2" value="#{TheBackingBean.theProperty}"/>
then JSF will only do:
TheBackingBean.setTheProperty(field1.value);
during the submission phase.

Resources