2011-04-11 56 views
8

将datacolumn绑定到数据源中可能存在或可能不存在的属性的最佳方法是什么?JSF和表达式语言:仅在绑定属性存在时

例如,当您有一个类层次结构,其中一些子类可能是具有该属性的子类型时,会发生这种情况。数据源包含各种子类型。

<DataColumn outputText="#{item.property}" /> 

当属性不​​存在于其中一个子类中时,总是产生PropertyNotFoundException。我不希望将该属性包含在基类中,因为它不应该根据业务规则存在。

你会如何解决这个问题?

回答

2

我认为在这种情况下最好的方法是为视图层创建一个具有所有必要字段的自定义实体,并将要显示的项目转换为它。

0

为什么不具有基类的布尔属性,告诉您在子类中是否具有实际属性。这样,你可以很容易地使用三元运算在EL表达式,像这样:

<DataColumn outputText="#{item.hasProperty ? item.property : 'I don't have this property.'}" /> 

如果EL懒洋洋地计算表达式这可以工作,但我不知道,不能马上检查。但无论如何,这是一个想法。

7

如果不更改课程,最好的办法是在EL中做一种instanceof。您可以通过检查EL中的Object#getClass(),然后Class#getName()Class#getSimpleName()获得的(简单)类名来完成此操作。

假设与物业类具有完全限定名com.example.SubItem,这里有一个例子:根据此模型

<h:outputText value="#{item.property}" rendered="#{item.class.name == 'com.example.SubItem'}" /> 

<h:outputText value="#{item.property}" rendered="#{item.class.simpleName == 'SubItem'}" /> 
+0

我尝试使用#{item.class}时遇到了问题,但与#{item.getClass()}配合良好 – 2012-07-06 13:02:24

+0

任何想法如果在事先不知道类的情况下该怎么做? – 2014-07-09 19:52:03

0

我想你可能想要做一个在支持bean中做了很多工作,而不是试图使其在实际的JSF页面上工作。

您可以将表格只是绑定到bean作为

<h:dataTable binding="#{myBean.dataTable}" /> 

//BEAN 
HtmlDataTable dataTable; 

public DataTable getDataTable() 
{ 
    dataTable = new HtmlDataTable(); //etc... 
    //add the columns here based on the logic in code 
} 

,然后实际做豆腐内呈现动态地添加成分等..如果你正在寻找模型分离和你需要页面成为一个非常受控制的bean,那么上面的答案实际上就是你所追求的。

或者如建议的那样,只需使用呈现的属性并检查类名(注意空指针)。我经常做这两件事,这实际上取决于我在实际的JSF中会有多少复杂的布尔逻辑。

4

作为在EL中提供instanceof功能的替代方法,您可以考虑将isInstanceOf()方法添加到ApplicationScoped bean。我使用类似:

@ManagedBean(name="app") 
@ApplicationScoped 
public class ApplicationController implements Serializable { 
    public boolean isInstanceOf(Object o, String className) throws ClassNotFoundException { 
     return Class.forName(className).isInstance(o); 
    } 
} 

然后我把它从EL这样的:

<... rendered="#{app.isInstanceOf(someObject, 'java.lang.Object')}"> 

有了一些调整,这种想法可以推广到方便调用从EL任何静态方法。