I've created custom Converter for when I output java.math.BigDecimal. When the BigDecimal is 0.00 or null
I want output a dash.
Here is my XHTML
<p:dataTable value="#{bean.data}" var="item">
<p:column>
<h:outputText value="#{item.currentValue}">
<f:converter converterId="my.bigDecimalConverter" />
</h:outputText>
</p:column>
</p:dataTable>
The problem I have is when #{item.currentValue} is null
the getAsString
method in the Converter is not called.
@FacesConverter("my.bigDecimalConverter")
public class BigDecimalConverter implements Converter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (context == null || component == null) {
throw new NullPointerException();
}
if (value == null) {
System.out.println("null=");
return "--";
}
System.out.print("Class=" + value.getClass());
if (value instanceof String) {
System.out.println("Str=" + value);
return (String) value;
}
if (value instanceof BigDecimal) {
BigDecimal bd = (BigDecimal)value;
if (bd.equals(new BigDecimal("0.00"))) {
return "--";
} else {
return bd.toPlainString();
}
}
return "";
}
}
I'm saying its not called because I get no errors and no println
statement output when the BigDecimal is null
. When the BigDecimal is not null
it works as expected and "Class=class java.math.BigDecimal" gets printed out and when the BigDecimal is 0.00 I do get --
outputted on the page.
I'm using JSF 2.1, Mojarra 2.1.27
I also using the following to test my converter.
<h:outputText value="#{null}">
<f:converter converterId="my.bigDecimalConverter" />
</h:outputText>
Reading over this question it would seem that a converter should work with a null
value.
https://stackoverflow.com/a/19093197/50262
The link you posted says that a converter should work with a null but doen't say a converter will be called in every situation with null values.
Concretely it don't says a converter will be called when it is inside a h:outputText
and the value is null.
If you dig in the Mojarra sources you'll see:
//Line 355 -- com.sun.faces.renderkit.html_basic.HtmlBasicRenderer
//method getCurrentValue
Object currentObj = getValue(component);
if (currentObj != null) {
currentValue = getFormattedValue(context, component, currentObj);
}
It's clear that a null value will never be converted! And I couldn't find a workaround.
Then if you really need your value to be null (you could return 0 or something) I think your only chance is making a custom renderer. It is very easy:
You write a renderer that overrides the method that matters:
package my;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import com.sun.faces.renderkit.html_basic.TextRenderer;
public class HtmlCustomRenderer extends TextRenderer {
@Override
public String getCurrentValue(FacesContext context, UIComponent component) {
if (component instanceof UIInput) {
Object submittedValue = ((UIInput) component).getSubmittedValue();
if (submittedValue != null) {
// value may not be a String...
return submittedValue.toString();
}
}
String currentValue = null;
Object currentObj = getValue(component);
//Remove the 'if' to call getFormattedValue even if null
currentValue = getFormattedValue(context, component, currentObj);
return currentValue;
}
}
And then we declare the renderer in faces-config.xml:
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>javax.faces.Text</renderer-type>
<renderer-class>my.HtmlCustomRenderer</renderer-class>
</renderer>
</render-kit>
Now your converter will be called with null values!
I hope it will help!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With