gpt4 book ai didi

jsf - 在 p :dataTable filters 中显式使用隐式 JSF 转换器 javax.faces.convert.EnumConverter

转载 作者:行者123 更新时间:2023-12-04 22:32:40 25 4
gpt4 key购买 nike

枚举:

public enum OrderStatus {

New("New"),
Paid("Paid"),
Shipped("Shipped"),
Completed("Completed");

private final String label;

private OrderStatus(String label) {
this.label = label;
}

public String getLabel() {
return label;
}
}

使用 enum输入 <p:dataTable>过滤如下。

<p:dataTable var="row"
value="#{testBacking}"
lazy="true"
rows="10"
widgetVar="dataTableUIWidget">

<p:column id="id" headerText="Id">
<h:outputText value="#{row.orderId}"/>
</p:column>

<p:column headerText="Order Status" filterBy="#{row.orderStatus}">
<f:facet name="filter">
<p:selectOneMenu onchange="PF('dataTableUIWidget').filter();">
<f:selectItem itemLabel="Select" itemValue=""/>

<f:selectItems var="orderStatus"
value="#{enumBean.orderStatus}"
itemLabel="#{orderStatus.label}"/>
</p:selectOneMenu>
</f:facet>

<h:outputText value="#{row.orderStatus}"/>
</p:column>
</p:dataTable>

row.orderStatus是上述enum的一种在其关联的 JPA 实体中。

<p:selectOneMenu> 关联的过滤器需要指定javax.faces.convert.EnumConverter明确地,因为它的值没有绑定(bind)到支持 bean 属性(否则适当的转换器会根据关联的支持 bean 中的属性类型隐式地自行适本地发挥其作用)。

我希望如下提及转换器

<f:converter converterId="javax.faces.Enum"/>

应该像其他隐式转换器一样工作。

然而,这会导致问题(当 <f:converter> 如上所述指定时)。

Severe: JSF1006: Cannot instantiate converter of type javax.faces.Enum

这个转换器有什么问题?我正在寻找一个可行的解决方案。

使用 PrimeFaces 5.2 final/Mojarra 2.2.12。


补充:

converter指定 javax.faces.Enum作为 converterId .

public class EnumConverter implements Converter, PartialStateHolder {

public static final String CONVERTER_ID = "javax.faces.Enum";
public static final String ENUM_ID = "javax.faces.converter.EnumConverter.ENUM";
public static final String ENUM_NO_CLASS_ID = "javax.faces.converter.EnumConverter.ENUM_NO_CLASS";
private Class<? extends Enum> targetClass;
private boolean isTransient;
private boolean initialState;

public EnumConverter() {}
}

因此,这应该通过指定 javax.faces.Enum 来工作。作为 convertId<f:converter>与其他隐式 JSF 转换器一样。

上述测试用例中使用的 bean(完全可选,需要同行评审):

@Named
@ViewScoped
public class TestBacking extends LazyDataModel<OrderTable> implements Serializable {

@Inject
private OrderService orderService;
private static final long serialVersionUID = 1L;

public TestBacking() {}

@Override
public List<OrderTable> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {

if (MapUtils.isNotEmpty(filters)) { // Debugging purpose only.
System.out.println("Enum filter : " + (filters.get("orderStatus") instanceof OrderStatus));
System.out.println("Filter value : " + filters.get("orderStatus"));
}

int rowCount = MapUtils.isNotEmpty(filters) ? orderService.rowCount(filters).intValue() : orderService.rowCount().intValue();
setRowCount(rowCount);

return orderService.getList(first, pageSize, null, filters);
}
}

stdout load() 中的语句方法显示以下输出。

Enum filter : false
Filter value : New

(很明显,filters.get("orderStatus") instanceof OrderStatus 返回 false,因为过滤器组件 <p:selectOneMenu> 没有通过转换器。它只是返回 String 而不进行转换)。

最佳答案

EnumConverter是一个特殊的转换器,只能用 Class<E> 构建。作为参数(最终设置为 targetClass )。没有它,转换器将无法工作。不幸的是,它不适用于所有枚举(即它实际上不是“通用枚举转换器”)。在那里你假设对枚举进行隐式/自动转换,它实际上是由 EL 强制完成的,而不是由 JSF EnumConverter .只要目标类型可解析为枚举,EL 确实对枚举提供了通用支持。

要显式使用JSF枚举转换器,基本上需要扩展EnumConverter如下所示,将目标枚举传递给 c'tor(无需覆盖 getAsString/Object() 方法):

@FacesConverter(value="orderStatusConverter")
public class OrderStatusConverter extends EnumConverter {

public OrderStatusConverter() {
super(OrderStatus.class);
}

}

然后改为引用它:

<f:converter converterId="orderStatusConverter" />

别忘了修改 <f:selectItem itemValue="">成为 itemValue="#{null}" , 否则你会得到一个 ClassCastExceptionjava.lang.String .

如果你碰巧使用 OmniFaces ,也可以使用它的generic enum converter而是:

<f:converter converterId="omnifaces.GenericEnumConverter" />

关于jsf - 在 p :dataTable filters 中显式使用隐式 JSF 转换器 javax.faces.convert.EnumConverter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33339315/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com