2

In a legacy code base, I came across this:

@javax.faces.convert.FacesConverter(forClass = java.lang.String.class)
public class WhitespaceToNullConverter implements Converter {
    @Override
    public Object getAsObject(FacesContext facesContext, UIComponent c, String value) {
        if (value == null || value.trim().isEmpty()) {
            if (c instanceof EditableValueHolder) {
                ((EditableValueHolder) c).setSubmittedValue(null);
            }
            return null;
        }
        return value;
    }

    // ...
}

First, isn't the passed UIComponent always an EditableValueHolder? Is that check needed?

Second, should a Converter change the UIComponent it's called for? That seems odd to me, assuming that the component's value is probably used to populate the UIComponent anyway.

The JavaDoc doesn't say anything in that regard.

Robert
  • 7,394
  • 40
  • 45
  • 64

1 Answers1

3

First, isn't the passed UIComponent always an EditableValueHolder?

Normally, getAsObject() is only called when JSF needs to convert a submitted value to a model value. Normally, this is only called in UIInput#validate(). And UIInput implements EditableValueHolder. So, assuming normal circumstances, the answer to this specific question is "Yes".


Is that check needed?

No, but it is not a "bad practice" either. It was likely written by a defensive programmer who just wanted to avoid questions popping up when one abuses the converter for a purpose it wasn't designed for ;)


Second, should a Converter change the UIComponent it's called for?

Depends on the purpose of the change. Usually indeed not, programmatically manipulating the JSF component tree from user code on is a poor practice, but sometimes there's simply no other way and then you have to hack around.


That seems odd to me, assuming that the component's value is probably used to populate the UIComponent anyway.

This specific converter solves two separate problems as described in following related questions:

Only strange thing here is that the setSubmittedValue(null) solution to the first problem is JSF 1.x specific while the application is apparently using JSF 2.x, as evidenced by presence of @FacesConverter. It's most likely overlooked during a previous JSF 1.x to 2.x migration. In JSF 2.x the setSubmittedValue(null) task of this specific converter can entirely be replaced by below context parameter:

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

That should make the converter not to look hacky anymore.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555