JSF и язык выражений: привязывать свойство только тогда, когда оно существует - PullRequest
9 голосов
/ 11 апреля 2011

Каков наилучший способ связать столбец данных со свойством, которое может существовать или не существовать в источнике данных?

Это происходит, например, когда у вас есть иерархия классов, где некоторые дочерние элементы могут иметь подтип, который имеет свойство. Источник данных содержит различные типы подклассов.

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

всегда выдает исключение PropertyNotFoundException, когда свойство отсутствует ни в одном из подклассов. Я не хочу включать свойство в базовый класс, потому что оно не должно быть там в соответствии с бизнес-правилами.

Как бы вы решили эту проблему?

Ответы [ 5 ]

8 голосов
/ 11 апреля 2011

Не меняя классов, вам лучше всего набрать instanceof в EL. Это можно сделать, проверив (простое) имя класса, полученное с помощью Object#getClass(), а затем Class#getName() или Class#getSimpleName() в EL.

Предполагая, что класс со свойством имеет полное имя 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'}" />
4 голосов
/ 19 марта 2013

В качестве альтернативного способа обеспечения функциональности instanceof в EL, вы можете рассмотреть возможность добавления метода isInstanceOf() к компоненту ApplicationScoped.Я использую что-то вроде:

@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.

3 голосов
/ 13 апреля 2011

Я думаю, что лучший способ в таком случае - создать пользовательский объект для уровня представления со всеми необходимыми полями и преобразовать в него элементы, которые вы хотите отобразить.

0 голосов
/ 11 апреля 2011

В зависимости от вашей модели здесь, я думаю, вы можете захотеть сделать намного больше работы с компонентом поддержки, а не пытаться заставить его работать на реальной странице 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-компонента путем динамического добавления компонентов и т. д. Если вы хотите отделить модель и вам нужна страница, которая должна быть очень управляемым bean-компонентом, тогдаПриведенные выше ответы действительно больше того, что вы ищете.

В качестве альтернативы, как предложено, просто используйте отображаемое свойство и проверьте имя класса (остерегайтесь нулевых указателей).Я делаю оба на регулярной основе, это действительно зависит от того, насколько сложная логическая логика у меня будет в реальном JSF.

0 голосов
/ 11 апреля 2011

Почему бы не иметь логическое свойство базового класса, которое говорит вам, есть ли у вас фактический атрибут в подклассах или нет.Таким образом, вы можете легко использовать троичный оператор в своем выражении EL, например:

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

Это может сработать, если EL вычисляет выражение лениво, но я не уверен и не могу проверить это прямо сейчас,Но в любом случае это идея для начала.

...