I need to convert null
property values of type java.math.BigDecimal
to 0.00
everywhere with a specified number of decimal places (only for displaying (<h:outputText>
) thus, not for input components).
The basic converter expected to do this job is given below (currency, percentage, locale etc have been excluded completely for brevity).
@FacesConverter("bigDecimalConverter")
public final class BigDecimalConverter implements Converter {
private static final int SCALE = 2;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
return null;
}
try {
return new BigDecimal(submittedValue).setScale(SCALE, RoundingMode.HALF_UP).stripTrailingZeros();
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Message"), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
BigDecimal value;
if (modelValue == null) { // This is expected to replace null with 0.
value = BigDecimal.ZERO;
} else if (modelValue instanceof Long) {
value = BigDecimal.valueOf((Long) modelValue);
} else if (modelValue instanceof Double) {
value = BigDecimal.valueOf((Double) modelValue);
} else if (!(modelValue instanceof BigDecimal)) {
throw new ConverterException("Message");
} else {
value = (BigDecimal) modelValue;
}
NumberFormat numberFormat = NumberFormat.getNumberInstance();
numberFormat.setGroupingUsed(true);
numberFormat.setMinimumFractionDigits(SCALE);
numberFormat.setMaximumFractionDigits(SCALE);
return numberFormat.format(value);
}
}
Referring to a property of the associated model or bean of type java.math.BigDecimal
using output components like the following.
<h:outputText value="#{bean.value}">
<f:converter converterId="bigDecimalConverter"/>
</h:outputText>
bean.value
is a type of java.math.BigDecimal
in a managed bean. If bean.value
is null
, then the getAsString()
method is not invoked. Hence, an empty output is rendered where a value of zero is expected.
This value="#{bean.value}"
needs to be changed to value="#{empty bean.value ? 0 : bean.value}"
for the converter to perform its coherent task.
Putting this conditional test in EL everywhere is however, quite maintenance-unfriendly.
Is there a way to invoke the getAsString()
method, when a target property is null
which is conditionally attempted to be set to 0
in that method (BigDecimal.ZERO
)?
Update :
The getAsString()
method is invoked with <o:param>
(OmniFaces).
<h:outputFormat value="Discount ({0}%)">
<o:param value="#{bean.value}">
<f:converter converterId="bigDecimalConverter"/>
</o:param>
</h:outputFormat>
This displays Discount (0.00%)
after has been converted by the converter, when #{bean.value}
returns null
.