The division of two integers is resulting in a floating point value.
Is there a way to get the result as an integer in the following situation?
<p:commandButton value="#{bean.intA / bean.intB}" ../>
The result should be shown as "1" not as "1.0".
EL doesn't support upcasting/formatting. An universal solution would be to create a custom EL function referring the below utility method:
public static String formatNumber(Number number, String pattern) {
if (number == null) {
return null;
}
DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance(getLocale());
formatter.applyPattern(pattern);
return formatter.format(number);
}
You can then use it as below:
<p:commandButton value="#{util:formatNumber(bean.intA / bean.intB, '#')}" ... />
In case you happen to use JSF utility library OmniFaces, it's available as #{of:formatNumber()} whose source code is actually copied above.
Related
I have Upgrade my project from JSFContainer 2.2 to JSFContainer 2.3
<p:selectManyListbox id="acl" value="#{controller.process.basisList}" >
<f:selectItems value="#{controller.filinglist}" />
</p:selectManyListbox>
filinglist has class object like ob(1L, 'data1');
basisList with generic type String
when working with JSFContainer 2.2, CDI 1.2 and EL 3.0. it's working fine the Long data has been stored as String in basisList List. I understand the this concept in below URL
Java Reflection API
But in JSFContainer 2.3, CDI 2.0 and EL 3.0. I got the below error
when I run the code
for(String i : basisList) {
System.out.println(i);
}
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String.
I debug using below code
for(Object i : basisList) {
System.out.println(i.getClass() + " > " + i);
}
The output what am getting is below
class java.lang.Long > 3
This behavior is correct when you upgrade from JSF 2.2 to JSF 2.3. Previously, JSF 2.2 and older didn't auto-convert these values which was actually not the expected behavior.
It's specified in UISelectMany javadoc for JSF 2.3.
Obtain the Converter using the following algorithm:
If the component has an attached Converter, use it.
If not, look for a ValueExpression for value (if any). The ValueExpression must point to something that is:
An array of primitives (such as int[]). Look up the registered by-class Converter for this primitive type.
An array of objects (such as Integer[] or String[]). Look up the registered by-class Converter for the underlying element type.
A java.util.Collection. Do not convert the values. Instead, convert the provided set of available options to string, exactly as done during render response, and for any match with the submitted values, add the available option as object to the collection.
If for any reason a Converter cannot be found, assume the type to be a String array.
The emphasized section of the above blockquote is new since JSF 2.3 (to compare, here's the JSF 2.2 variant of UISelectMany javadoc).
You need to fix your basisList to become of exactly same type as filinglist, or else you'll need to attach an explicit Converter.
You basisList is probably of type <Object> so when you create your for loop with a String Java tries to cast that value into the String variable i. In your case it seems that you have a list partially, or fully filled with primitive long types which can't just be cast to a string. You could write some code like this which would support both cases.
List<Object> basisList = new ArrayList<>();
for (Object o : basisList) {
if (o instanceof String) {
System.out.println(o.toString());
} else if(o instanceof Long){
System.out.println(Long.toString((Long) o));
} else {
System.out.println("Some other type = " + o.toString());
}
}
I have an input place that should get a number. I want it to be displayed as empty. However when I run my program, I get 0 or 0.00 as default. How can I make it empty?
This will happen if you bound the value to a primitive instead of its wrapper representation. The primitive int always defaults to 0 and the primitive double always defaults to 0.0. You want to use Integer or Double (or BigDecimal) instead.
E.g.:
public class Bean {
private Integer number;
// ...
}
Then there are two more things to take into account when processing the form submit. First, you need to instruct JSF to interpret empty string submitted values as null, otherwise EL will still coerce the empty string to 0 or 0.0. This can be done via the following context parameter in web.xml:
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
Second, if you're using Tomcat/JBoss or any server which uses Apache EL parser under the covers, then you need to instruct it to not coerce null to 0 or 0.0 in case of Number types by the following VM argument (it's unintuitively dealing with Number types as if they are primitives):
-Dorg.apache.el.parser.COERCE_TO_ZERO=false
See also:
The empty string madness
h:inputText which is bound to Integer property is submitting value 0 instead of null
h:inputText which is bound to String property is submitting empty string instead of null
javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL does not work anymore since Java EE 7 / EL 3.0
I don't disagree with previous answers given, but I think you might be looking for
<h:inputText id="number" binding="#{controller.inputBox}" value="#{controller.number}" >
<f:event type="preRenderComponent" listener="#{controller.preRenderInput}" />
</h:inputText>
and inside the controller
private double number; // getters and setters
private UIInput inputBox; // getters and setters
public void preRenderInput() {
// if it is the first request
if(!FacesContext.getCurrentInstance().isPostback()) {
inputBox.setValue("");
}
}
JSF 2.0+
You can use inputNumber in primefaces-extension instead of inputText.
Like this
<pe:inputNumber />
In your XHTML code, assume you have your input field as :
<h:inputText id="newname" value="#{youAction.newName}"
style="width:130px" styleClass="form">
</h:inputText>
In your Managed Bean Action Class, map this field as :
#ManagedBean(name="yourAction")
public class YourAction {
private String newName;
...
// Add Getter & Setter Methods
...
}
By doing in this way, you won't get 0 or 0.00 as default value in your input fields.
I want to display name (current user) in a drop down list in JSF. Here name is a dynamic variable that gets populated though some pojo class. The present code that I have is
<f:selectItem itemLabel="#{accessManager.salesManager.displayName} #{' ('.concat(i.m['current user']).concat(') ')}" itemValue="#{accessManager.salesManager.oid}" />
accessManager.salesManager.displayName populates the name on the UI.
#{' ('.concat(i.m['current user']).concat(') ')}" here I am trying to hard code (current user).
But this is throwing exceptions.
Can any one help me in this? It sounds to be a very simple query but I am not used to EL.
Based on your example, the easiest way is to provide an extra function in your managed bean which evaluates if the current user is the current choice or not. Later on, you evaluate that function with a ternary operator, which will decide wether to display the bundled (translated) value or not.
#ViewScoped
public class ChoiceBean{
public List<SalesManager> getSalesManagers(){
return salesManagers;
}
//Checks if your current choice is the current manager(EL 2.2 required to pass the parameter)
public boolean checkIfCurrent(SalesManager manager){
if (manager.getName().equals("Bob")) return true;
return false;
}
}
<f:selectItem
itemLabel="#{manager.name} #{choiceBean.checkIfCurrent(manager) ? i.m['current user'] : ''}" itemValue="#{salesManager.oid}" />
See also:
Passing parameter to JSF action
Ternary operator in JSTL/EL
Another solution is to use a function doing this String concatenation for you. Either
you use the JSTL functions library with fn:join (see enter link description here) or
implement your own static method in EL, and use that one. The method itself would (surprisingly) look like
public static String concat(String string1, String string2) {
return string1.concat(string2);
}
and the call in JSF, nested like #{fn:concat('(',fn:concat(i.m['current user'],')'))}.
But, out of curiosity, why don't you want to add the brackets into the properties file, so the ressource-value holds (current user) instead of current user?
Hope it helps...
So the question is how do I concat '(' & ')' before and after #{i.m['current user'])}
Don't do it the hard way. Just put those parentheses outside the EL expression.
<f:selectItem itemLabel="#{accessManager.salesManager.displayName} (#{i.m['current user']})" itemValue="#{accessManager.salesManager.oid}" />
I have an input place that should get a number. I want it to be displayed as empty. However when I run my program, I get 0 or 0.00 as default. How can I make it empty?
This will happen if you bound the value to a primitive instead of its wrapper representation. The primitive int always defaults to 0 and the primitive double always defaults to 0.0. You want to use Integer or Double (or BigDecimal) instead.
E.g.:
public class Bean {
private Integer number;
// ...
}
Then there are two more things to take into account when processing the form submit. First, you need to instruct JSF to interpret empty string submitted values as null, otherwise EL will still coerce the empty string to 0 or 0.0. This can be done via the following context parameter in web.xml:
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
Second, if you're using Tomcat/JBoss or any server which uses Apache EL parser under the covers, then you need to instruct it to not coerce null to 0 or 0.0 in case of Number types by the following VM argument (it's unintuitively dealing with Number types as if they are primitives):
-Dorg.apache.el.parser.COERCE_TO_ZERO=false
See also:
The empty string madness
h:inputText which is bound to Integer property is submitting value 0 instead of null
h:inputText which is bound to String property is submitting empty string instead of null
javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL does not work anymore since Java EE 7 / EL 3.0
I don't disagree with previous answers given, but I think you might be looking for
<h:inputText id="number" binding="#{controller.inputBox}" value="#{controller.number}" >
<f:event type="preRenderComponent" listener="#{controller.preRenderInput}" />
</h:inputText>
and inside the controller
private double number; // getters and setters
private UIInput inputBox; // getters and setters
public void preRenderInput() {
// if it is the first request
if(!FacesContext.getCurrentInstance().isPostback()) {
inputBox.setValue("");
}
}
JSF 2.0+
You can use inputNumber in primefaces-extension instead of inputText.
Like this
<pe:inputNumber />
In your XHTML code, assume you have your input field as :
<h:inputText id="newname" value="#{youAction.newName}"
style="width:130px" styleClass="form">
</h:inputText>
In your Managed Bean Action Class, map this field as :
#ManagedBean(name="yourAction")
public class YourAction {
private String newName;
...
// Add Getter & Setter Methods
...
}
By doing in this way, you won't get 0 or 0.00 as default value in your input fields.
I'm storing value expressions in a JSF component with the f:attribute tag, e.g.:
<h:inputText ...>
<f:attribute name="myId1" value="#{bean.prop1}" />
<f:attribute name="myId2" value="#{bean.prop2}" />
<f:attribute name="myId3" value="#{bean.prop3}" />
</h:inputText>
Is there a way to access all of those value expressions programmatically? (without knowlegde of the names myId1, myId2,...)
Section 9.4.2 of the JSF 2.1 specification says that those values are stored "in the component’s ValueExpression Map".
That's the only occurrence of the term "ValueExpression Map" in the complete spec.
How do I access that map?
In the UIcomponent's Method getValueExpression() of the Jboss/Mojarra implementation the map
getStateHelper().get(UIComponentBase.PropertyKeys.bindings)
is used to obtain a single value expression.
I guess that map is a super set of the "ValueExpression Map"?
Can I be sure that all implementations and all inherited (standard) components use that map to store ValueExpressions?
Thanks.
In theory you should be able to see them all by UIComponent#getAttributes():
Map<String, Object> attributes = component.getAttributes();
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
System.out.printf("name=%s, value=%s%n", entry.getKey(), entry.getValue());
}
However, that doesn't work the way as you'd expect. It only returns static attributes. This does not seem to ever going to be fixed/implemented. See also JSF issue 636. I'd suggest to stick to attribtues with predefinied prefix and an incremental numerical suffix, like as you've presented in your example. That's also what I've always used to pass additional information from the component on to custom validators and converters. You can just collect them as follows:
Map<String, Object> attributes = component.getAttributes();
List<Object> values = new ArrayList<Object>();
for (int i = 1; i < Integer.MAX_VALUE; i++) {
Object value = attributes.get("myId" + i);
if (value == null) break;
values.add(value);
}
System.out.println(values);
An alternative to the answer given by BalusC might be to use nested facets or UIParameter components. Facets can be retrieved as a map using getFacets but you probably need to put an additional UIOutput inside each facet to access its value expression.
Nested UIParameters can be accessed by iterating over the components children and checking for instanceof UIParameter. UIParameters have name and value attributes and so could be easily converted to a map.
I have used parameters in a custom component, but I'm not sure how a standard UIInput like in your example reacts to these.
BalusC is right. UIComponent#getAttributes().get(name) gets values from both places - at first from attributes map and then if not found from "value expression map". To put some value you have to call UIComponent#setValueExpression(name, ValueExpression). If value is literal, it gets stored into the attribute map, otherwise into the "value expression map". Everything is ok then.