javax.el.PropertyNotWritableException when using EL conditional operator in value of UIInput - jsf

I get this error message:
javax.el.PropertyNotWritableException: /u/editProfile.xhtml #64,140 value="#{empty userProfile.cfg.gpu or userProfile.cfg.gpu == '' ? usernavmsg.EditMe: userProfile.cfg.gpu}": null
The problem is that when the value of a bean property is null the value of an inputText field switches from my ManagedBean property, to a resource string. So I cannot persist that value.
I request the profile of the user from my database in my managed bean. If a property of the said profile is null, the inplace text holder value is "Edit Me". If it's not null it's the value of that property. Which is working ! However when I submit the form and try to persist a new value or no value at all the error appears. The error only appears for the field that are null to begin with (when I requested them from the db). So the problem is that when the value is null it switch from my ManagedBean property, to a resource string.
I just have a form with this:
<h:outputLabel value="#{usernavmsg.GPU}: "/>
<p:inplace styleClass="lessDark">
<p:inputText value="#{empty userProfile.cfg.gpu ? usernavmsg.EditMe: userProfile.cfg.gpu}" />
</p:inplace>
when I submit the form I want to persist userProfile.cfg in the database which doesn't happen.
Can I work around this ? Is it even possible ?

Conditional statements in EL are indeed not writable. They are read-only. End of story. The same applies to method references in EL as in #{bean.property()}. It must really be a true value expression as in #{bean.property}.
Your approach of using a (HTML5) "placeholder" is actually wrong. For that you should be using the placeholder attribute, not the value attribute. In older versions of PrimeFaces that do not have a placeholder attribute you'll need passthrough.
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<p:inputText value="#{userProfile.cfg.gpu}" a:placeholder="#{usernavmsg.EditMe}" ... />
Nowadays PrimeFaces offers a placeholder attribute.
<p:inputText value="#{userProfile.cfg.gpu}" placeholder="#{usernavmsg.EditMe}" ... />

Related

JSF input processing order

Is there a way to specify the order in which the inputs should be set after a submit?
Here is my case:
<h:inputText id="fieldA" value=#{myBean.myObject.fieldA}" />
<h:inputText id="fieldB" value=#{myBean.myObject.fieldB}" />
<p:autoComplete id="myObject" value=#{myBean.myObject" converter="myObjectConverter" />
<h:inputText id="fieldC" value=#{myBean.myObject.fieldD}" />
<h:inputText id="fieldD" value=#{myBean.myObject.fieldC}" />
The issue I am encountering is that, as the inputs are processed in the ordered they are declared, fieldA and fieldB are set in the initial instance of myObject, then myObject is set (with a new instance thus filedA and fieldB values are lost), and finally fieldC and fieldD are set with no problem.
If I could manage to start by setting myObject first, that would solve my problem.
I will temporarily set the fields and myObject into two different attributes of my bean, and populate myObject after clicking a save button. But it looks more like a hack than a real solution.
Needless to say that declaring the autocomplete before the inputtexts is not an option.
Thanks in advance.
In shortcut:
You can use <p:inputText> tag from primefaces. Then, you can disable all inputs. Add ajax to your autoComplete, and update other inputs after processing autoComplete. Inputs disable attribute can be set to depend on whether the autoComplete is not null. This way you will make the user to enter the autoComplet first.
you can try to set immediate="true" to p:autocomplete, so that it will be processed in the APPLY_REQUEST_VALUES phase, before all other components.
The simple solution is to update h:inputTexts when p:autocomplete item is selected to reflect its values:
<p:autoComplete id="myObject" value="#{myBean.myObject}" ...>
<p:ajax event="itemSelect" process="#this" update="fieldA fieldB fieldC fieldD" />
</p:autoComplete>
but this reverts user inputs on h:inputTexts. And since you can't move p:autocomplete on top, probably this is not acceptable too.
In case you can't/don't want to use ajax, you can force an early model update:
<p:autoComplete id="myObject" value="#{myBean.myObject}" immediate="true"
valueChangeListener="#{component.updateModel(facesContext)}" ... />
but, in my opinion, this is not very user friendly...
P.S. this time it's tested :)
There's no pretty way to get around this; your situation is already less than ideal and is hacky (re: not being able to simply reorder the fields). One workaround is for you to set fieldA and fieldB as attributes of myObject. In the converter, you could then pull the values off the components. Observe
Set attributes thus
<h:inputText id="fieldA" binding=#{fieldA}" />
<h:inputText id="fieldB" binding=#{fieldB}" />
<p:autoComplete id="myObject" value=#{myBean.myObject" converter="myObjectConverter">
<f:attribute name="fieldA" value="#{fieldA}"/>
<f:attribute name="fieldB" value="#{fieldB}"/>
</p:autoComplete>
The binding attribute effectively turns those components into page-scoped variables, allowing you to then pass them as attributes on your p:autocomplete
Get the values of those variables in your converter
//Retrieve the fields and cast to UIInput, necessary
//to retrieve the submitted values
UIInput fieldA = (UIInput) component.getAttributes().get("fieldA");
UIInput fieldB = (UIInput) component.getAttributes().get("fieldB");
//Retrieve the submitted values and do whatever you need to do
String valueA = fieldA.getSubmittedValue().toString();
String valueB = fieldB.getSubmittedValue().toString();
More importantly, why can't you just reorder the fields/logical flow of your form? You can avoid all this nasty business if you did

h:button not passing f:param from a JSF component

I have a JSF 2 page with an <h:button>. I want to pass two <f:param> to the outcome page.
Value of <f:param> pOne comes from the page bean.
Value of <f:param> pTwo comes from an input field on the page.
pTwo's value is not stored on the page bean.
pTwo's input field value is set by javascript when user clicks on an image map within same page.
The problem is that the request passes null for param pTwo.
If I set the value of pTwo to a static value, value="12345", then 12345 is passed.
So, why does <f:param> not pass the value of a input field from the source page?
Thanks!
<input type="text" id="pTwo"/>
<h:button value="Go" outcome="destPage">
<f:param name="pOne" value=#{myBean.pOne}"/>
<f:param name="pTwo" value=#{pTwo}"/>
</h:button>
You cannot reference the value of the input field in an EL expression like this. Not even if you use h:inputText.
Furthermore, JSF calculates the link for the button including the parameters when the page is rendered on server side. So when the user sees the page and enters something in the input field, the URL for the link is already fixed and won't change.
To solve this in a similar way, you could use h:commandButton instead of h:button, submit the form including the value for pTwowith h:inputText and return a redirect to the new page. The XHTML for this could look like this:
<h:form>
<h:inputText value="#{bean.pTwo}"/>
<h:commandButton action="#{bean.goToDest}" value="Go"/>
</h:form>
The referenced action method could look like this:
public String goToDest() {
return "destPage?faces-redirect=true&pOne=" + pOne + "&pTwo=" + pTwo;
}
try use the following code:
<h:commandButton action="#{bean.goToDest}" value="Go" >
<f:setPropertyActionListener target="#{yourDestinyManagedBean.pOne}" value="#{yourManagedBean.pOne}" />
<f:setPropertyActionListener target="#{youDestinyManagedBean.pTwo}" value="#{yourManagedBean.pTwo}" />
</h:commandButton>
You can see an example here.

Avoid Date field showing as null in XHTML

I am rendering a date field in XHTML using JSF. Since the value in DB is saved as null the date field values is shown as "null" in the UI. How to avoid this null?
My code is given below:
<h:outputFormat value="{0, date, MM/dd/yyyy}"
rendered="#{sysbean.xx.isfeed == '1' or (sysbean.yy== false and sysbean.details.endate!= null)}">
<f:param value="#{sysbean.details.endate}" /></h:outputFormat>
The output I am getting is
Project Name : null
How can I avoid the value coming as "null"?
<f:param value="#{value to check!=null?value when condition is true:
value when condition is false}" />
Checking the null at EL expression,
or in the bean also you can put the inline check for null values.

Dynamic Action in JSF page

I have a JSF page. My CommandButton action method value is dependent on the bean variable value.
Example:
Bean headerBean has varaible actionValue with value "someBean.doAction1()"
When I use , It says headerBean.actionValue is not a method which is right.
How can I get the action value as "someBean.doAction1" instead of headerBean.actionValue.
Thanks,
You can use the brace notation for that.
<h:commandButton value="submit" action="#{someBean[headerBean.actionValue]}" />
When the #{headerBean.actionValue} returns a String of for example doAction1, then this will effectively invoke #{someBean.doAction1}.
If the bean name to be called is currently actually in the actionvalue (headerBean.actionValue returning someBean.doAction1), you need to split it into a field that returns the bean name and one that returns the method name and then use
<h:commandButton value="submit" action="#{requestScope[headerBean.beanName][headerBean.actionValue]}" />
If headerBean.beanName returns 'someBean' and headerBean.actionValue returns doAction1 the above will call #{somebean.doAction1}.

JSF: Ternary operator used to assign a value to an <f:param> fails

I am using JSF tags within an XHTML file. My intention is to enable or disable a <rich:MenuItem> context-menu item by setting the "disabled" attribute to "true" or "false" appropriately. To do this, I am using a backing bean variable in a ternary operator and setting an <f:param> value to either "true" or "false" based on the bean variable, as below:
<rich:componentControl event="oncontextmenu" for="network-tree-menu"
operation="show">
<f:param id="nestlevel" value="#{item.nestLevel > 10 ? 'true' : 'false'}"
name="nestlevel" />
</rich:componentControl>
where item is the backing bean and item.nestLevel is an integer.
I am using this <f:param> value later in the XHTML file as below:
<rich:contextMenu ...
<rich:menuItem id="abc" ajaxSingle="true" disabled="{nestlevel}"
onclick="doSomething();" value="Do something...">
</rich:contextMenu>
This is not working !! The menu item is always enabled, (I guess this is the default behaviour) even though the result of the ternary operation is "true". Is there something I am missing here w.r.t the syntax, or is there some other way I can do this conditional enabling of context-menu items within the XHTML file?
Thanks in advance.
Regards,
Nagendra U M
How about this:
<f:param id="nestlevel" value="#{item.nestLevel > 10}" name="nestlevel" />

Resources