В JSP EL значение перечисления всегда пустое

При попытке заставить работать условие EL я обнаружил, что значения перечисления полностью игнорируются. Мне кажется, что это противоречит спецификации.

<c:out value='${com.foobar.data.BookingStatus.FAILED}' />
<c:out value='${BookingStatus.FAILED}' />
<c:out value='${com.foobar.data.BookingStatus.failed}' />
<c:out value='${BookingStatus.failed}' />
<c:if test="${empty BookingStatus.FAILED }">empty</c:if>

К моему удивлению, все они оцениваются как пустые. Почему класс Enum не распознается? Это происходит в текущем стабильном экземпляре Tomcat.

Может ли это быть проблемой пути к классам? Enum успешно используется в коде контроллера, но больше нигде в JSP. Он поставляется в банке в каталоге lib развертывания.

ОБНОВЛЕНИЕ:

Мое намерение состоит в том, чтобы сравнить предоставленное целое число со свойством Enum следующим образом:

<c:when test='${bookingInformation.bookingStatus eq BookingStatus.FAILED.code}'>
    FOOBARFAIL
</c:when>

К сожалению, проверяемое значение не может быть изменено и останется целым числом. Enum выглядит следующим образом (упрощенно):

public enum BookingStatus {

    COMPLETED(0), FAILED(1);

    private final int code;

    private BookingStatus(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

}

Я хочу избежать жесткого кодирования целочисленного значения FAIL и т. д. и вместо этого использовать перечисление для сравнения.


person sibidiba    schedule 05.01.2011    source источник
comment
stackoverflow.com/questions/123598 /   -  person jmj    schedule 05.01.2011
comment
Нет это не так. У меня нет проблем с условием, но тогда сам объект Enum недоступен, он пустой/нулевой. Это как Tomcat вообще не увидит класс Enum.   -  person sibidiba    schedule 05.01.2011


Ответы (3)


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

Неясно, каково ваше намерение, но приятно знать, что вы можете сравнивать свойства перечисления как String в EL. Именно они разрешены как String.

Предполагая, что у вас есть bean-компонент, который выглядит так:

public class Booking {
    public enum Status { NEW, PROGRESS, SUCCESS, FAILED }

    private Status status;

    public Status getStatus() {
        return status;
    }
}

Затем вы можете проверить условие Status.FAILED следующим образом:

<c:if test="${booking.status == 'FAILED'}">
    Booking status is FAILED.
</c:if>

Смотрите также:

person BalusC    schedule 05.01.2011
comment
Проблема в том, что я сравниваю с целым числом, порядковым значением перечисления, а не с другим перечислением. Могу ли я преобразовать целое число в перечисление в EL? - person sibidiba; 05.01.2011
comment
Не используйте порядковые номера. Используйте полноценные значения перечисления. Ваш getStatus() должен вернуть Status, а не int. Это признак плохо спроектированной модели. Порядковые числа не являются константами. Они могут меняться всякий раз, когда вы добавляете/удаляете/переставляете значения перечисления. Это звучит так, как будто вы делаете это как (плохой) обходной путь, чтобы иметь возможность сохранять перечисления Java в/из базы данных. Тогда это другая тема. - person BalusC; 05.01.2011
comment
Читая ваш ответ еще раз, означает ли это, что я в принципе не могу использовать общедоступный класс enum в EL? - person sibidiba; 05.01.2011
comment
Нет. EL не поддерживает его. Он поддерживает только Javabeans, как описано в спецификации Javabeans. Вы можете добавить геттер, который возвращает все значения статуса, но это просто неуклюже. Вы должны решить эту проблему на другом уровне: т.е. использовать не порядковые номера, а перечисления. - person BalusC; 05.01.2011
comment
Я полностью осознаю, что должно быть предоставлено перечисление, но ситуация намного сложнее, и я мог бы просто изменить несвязанные свойства класса. Это часть довольно ОГРОМНОГО приложения. - person sibidiba; 05.01.2011
comment
Это не только перечисления. EL не поддерживает доступ к классам по полному имени класса, а также доступ к общедоступным статическим конечным константам и т.д. Но сказать, что EL отстой, — это слишком далеко. Это просто никогда не было намерением EL. Он разработан на основе спецификации Javabeans. Если вы хотите использовать не-Javabeans в EL, что ж... Лучшее, что вы можете сделать, это добавить еще один геттер, который выполняет желаемую работу в модели. - person BalusC; 05.01.2011
comment
Я просто считаю, что спецификация EL заходит слишком далеко, чтобы ограничивать вас. Хуже того, это побуждает новичков использовать скриптлеты вместо этого, которые ужасны, потому что они вообще не ограничивают их, подсовывая бизнес-логику в JSP. EE6 предлагает некоторые новые возможности для исправления этого, такие как вызовы функций. Наконец-то вы сможете получить доступ к несовместимым с javabeans свойствам стандартной библиотеки Java! - person sibidiba; 06.01.2011

Как указал BalusC, вы не можете получить доступ к перечислениям с помощью EL, однако вы можете сделать это:

<c:set var="enumFailed" value="<%=BookingStatus.FAILED%>"/>

<c:if test="${enumFailed.code == bookingInformation.bookingStatus}">
    ...
</c:if>

Было бы идеально, если бы bookingInformation.bookingStatus было перечислением, а не целым числом, но если о рефакторинге вашего приложения не может быть и речи из-за его устаревшего характера, тогда мой приведенный выше пример должен помочь. Вам понадобится <c:set/> для каждого значения перечисления (в вашем примере их всего два).

person Steven Benitez    schedule 08.01.2011

Вы должны импортировать класс enum на свою страницу jsp. Поскольку вы импортируете его, вы можете ссылаться на него. Я написал пример ниже.

Мое перечисление - это WebSettingType.

public enum WebSettingType {

    SMTP_HOSTNAME("smtp_hostname"),
    SMTP_PORT("smtp_port"),
    SMTP_USERNAME("smtp_username");
    private final String value;

    private WebSettingType(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

У меня есть страница websettings.jsp, которая использует страницу тегов и т.д.

<%@page import="my.package.WebSettingType"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:admin>
    <jsp:attribute name="css">
    </jsp:attribute>
    <jsp:attribute name="content">
        <input type="text" name="${WebSettingType.SMTP_HOSTNAME.getValue()}"/>
    </jsp:attribute>
</t:admin>
person George Siggouroglou    schedule 26.04.2016
comment
На дату, когда был задан вопрос, это не поддерживалось в EL. См. Также принятый в настоящее время ответ и его ссылку См. также: stackoverflow.com/q/3732608 - person BalusC; 26.04.2016