应该 javax.faces.convert.Converter.getAsObject 修改传递的 UIComponent 吗?

Should javax.faces.convert.Converter.getAsObject modify the passed UIComponent?

在遗留代码库中,我遇到了这个:

@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;
    }

    // ...
}

首先,传递的 UIComponent 不总是 EditableValueHolder 吗?需要那张支票吗?

其次,Converter 是否应该更改它所要求的 UIComponent?这对我来说似乎很奇怪,假设组件的值可能用于填充 UIComponent 无论如何。

JavaDoc在这方面没有说什么。

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

通常,getAsObject() 仅在 JSF 需要将提交的值转换为模型值时调用。通常,这仅在 UIInput#validate() 中调用。 UIInput 实现了 EditableValueHolder。所以,假设正常情况下,这个具体问题的答案是“是”。


Is that check needed?

不,但这也不是“不好的做法”。它很可能是由一名防御性程序员编写的,他只是想避免在出于非设计目的滥用转换器时出现问题;)


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

取决于更改的目的。通常确实不是,从用户代码中以编程方式操作 JSF 组件树是一种糟糕的做法,但有时根本没有其他方法,然后你必须四处寻找。


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

这个特定的转换器解决了两个独立的问题,如以下相关问题所述:

  • h:inputText which is bound to String property is submitting empty string instead of null
  • .

这里唯一奇怪的是第一个问题的 setSubmittedValue(null) 解决方案是 JSF 1.x 特定的,而应用程序显然使用的是 JSF 2.x,[= 的存在证明了这一点16=]。它很可能在以前的 JSF 1.x 到 2.x 迁移过程中被忽略了。在 JSF 2.x 中,此特定转换器的 setSubmittedValue(null) 任务可以完全替换为以下上下文参数:

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

这应该会让转换器看起来不再那么古怪了。

另请参阅: