我一直在使用PrimeFaces SelectOneMenu对象中的转换器。如果我只告诉转换器指的是哪个类,它们工作正常:
@FacesConverter(forClass = DescriptorVO.class)
public class DescriptorVOConverter implements Converter { ... }
这样,我不必明确告诉JSF组件在填充类DescriptorVO
的对象时应该使用哪个转换器。
然而,我创建了一个使用p:SelectManyCheckbox
的页面,但我无法知道为什么它不会调用我的转换器。然后我给了它一个名字,如下:
@FacesConverter(forClass = RoleVO.class, value = "roleVOConverter")
public class RoleVOConverter implements Converter { ... }
并将其作为组件属性之一传递给
<p:selectManyCheckbox id="cbx_roles" required="true" converter="roleVOConverter"
requiredMessage="At least one role must be selected."
value="#{userView.selectedRoles}" layout="responsive">
<f:selectItems value="#{userView.roles}" var="role"
itemLabel="#{role.title}" itemValue="#{role}" />
</p:selectManyCheckbox>
和 voi la ,它开始正确调用转换器。这向我提出了一个问题,即我何时应该命名我的转换器(通过value
属性)并告诉他们转换器应该使用哪个类(具有forClass
属性)就足够了。在使用PrimeFaces时,我从未必须使用任何转换器,仅适用于此特定SelectManyCheckbox
组件。不同的组件对转换器有不同的必需品,或者我只是将转换器的概念弄错了?
答案 0 :(得分:4)
当value
组件的UISelectMany
引用类似java.util.Collection
的通用List<Role>
类型而非类似Role[]
的数组时,可能会发生这种情况。这在javadoc of UISelectMany
(强调我的)中指定:
使用以下算法获取
Converter
:
- 如果组件附加了
Converter
,请使用它。如果没有,请查找值
ValueExpression
(如果有)。ValueExpression
必须指向以下内容:
- 基元数组(例如
int[]
)。查找已注册的类Converter
以获取此基本类型。- 一组对象(例如
Integer[]
或String[]
)。查找已注册的基类Converter
以获取基础元素类型。- A
java.util.Collection
。请勿转换值。如果由于某种原因无法找到
Converter
,请假设该类型为String
数组。
原因是,泛型类型<Role>
在运行时丢失,不能直接确定。如果java.util.Collection
通过手动迭代<f:selectItem(s)>
来检查实际类型并确定{{1},则可以使用MyFaces代替Mojarra。基于第一个非Converter
值。
我在此创建了规范issue 1422以获得JSF规范并改进Mojarra。