JSF / Faces - f:attribute with null value not send to bean - jsf

Updating to mojarra 2.3.18 following f:attribute inside a component is not send to the server on ajax request.
<f:attribute name="foo" value="#{null}"/>
Is this by design?
As a workaround i am passing value="null" now and catching this String in the bean to convert it back to null.

Related

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.

Passing JSF 1.2 inputtext to a method in a session bean

I am learning JSF 1.2 and I have a scenario where a view "profile.jsf" is rendered using a request bean BeanProfile. The bean "BeanProfile" is a request bean because I need updated data in every request and refresh of the view. The view have a <h:commandButton/> that triggers a method in a session bean LoginBean and which should update the user profile before persisting it. So, I need to pass all the information in the profile view to the method in the session bean. I tried using the <f:attribute/> in the <h:commandButton/> like this:
<h:commandButton id="submit" actionListener="#{beanLogin.updateUser}" value="Update">
<f:attribute name="ttt" value="789"/> <!-- just for debug -->
<f:attribute name="name" value="#{name}" /> <!-- I will pass just that one for the moment -->
</h:commandButton>
and the component:
<h:inputText id="name"
binding="#{name}"
value="#{beanProfile.name}"
required="true" />
in my method i have:
public void updateUser(ActionEvent event) {
/*Debug*/
System.err.println("size: "+event.getComponent().getAttributes().size());
System.err.println("--"+(String) event.getComponent().getAttributes()
.get("ttt")+"--");;
UIInput input = (UIInput) event.getComponent().getAttributes().get("name");
String text = (String) input.getSubmittedValue();
System.err.println("++"+text+"++");
}
As a result I get:
2014-12-20T01:43:25.850+0100|Severe: size: 1
2014-12-20T01:43:25.850+0100|Severe: --789--
java.lang.NullPointerException ...
So I passed 2 parameters and I only got one in the method in the session bean and that's what caused the java.lang.NullPointerException. I don't know what i am doing wrong. I am working in Eclipse 4.4.1 SR1 using a dynamic web module 3.0 and GlassFish Server Open Source Edition 4.1 which includes Mojarra 2.2.7.
Update:
I tried the same code using tomcat 8.0.15, MyFaces 1.2.12 and JSTL 1.2 which I was already using with GlassFish and Mojarra. I have the same problem and I found that the bean injection thought the managed-property in faces-config.xml does not work either (null value) in both configurations I used.

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 does JSF load property values of managed bean?

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" />

Ajax and Validator is not working together

When I am trying to insert a validator to a selectOneMenu element containing a ajax listener in JSF, the ajax listener begins to not working. The following is my JSF snipplet specific to issue I am talking:
<h:selectOneMenu id="metalCodes" converter="metalCodeConverter" required="true" requiredMessage="#{lang.metalStockIntroducing_metalCode_req_txt}" value="#{metalStockIntroducingProcessesBean.metal.metalCode}">
<f:selectItem itemLabel="Please select..." noSelectionOption="true" />
<f:selectItems value="#{metalStockIntroducingProcessesBean.metalCodesMenu}" />
<f:ajax listener="#{metalStockIntroducingProcessesBean.changeMetalType}" event="change" execute="metalCodes" render="metalTypesMenu" immediate="false"/>
<f:validator validatorId="densityValidator"/>
</h:selectOneMenu>
What would you friends recommend me to do in order to make the validator and ajax listener works collaborately in a h:selectOneMenu JSF element?
They ought to work fine together. The ajax listener method will only not be invoked when the validator threw an exception. Make sure that your validator isn't incorrectly doing that. Make sure that you're re-rendering the <h:message> or <h:messages> associated with the input component as well so that you get notified of any faces messages during an ajax request. Or at least read the server logs, any queued-but-not-displayed faces messages will be logged there.

Resources