In JSP EL enum value always empty [duplicate]

2019-02-09 12:23发布

问题:

This question already has an answer here:

  • How to reference constants in EL? 12 answers

When trying to get an EL condition working I found that enum values are completely ignored. This seems to me contrary to the spec.

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

To my surprise these all evaluate to empty. Why is the Enum class not recognized? This is happening in a current stable Tomcat instance.

Can this be a classpath issue? The Enum is used successfully in controller code but nowhere else in JSPs. It is supplied in a jar in the lib directory of the deployment.

UPDATE:

My intention is to compare a supplied Integer to an Enum's property like this:

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

Unfortunately the value being checked can't be changed and will remain an Integer. The Enum looks as follow (simplified):

public enum BookingStatus {

    COMPLETED(0), FAILED(1);

    private final int code;

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

    public int getCode() {
        return code;
    }

}

I want to avoid to hard code the Integer value of FAIL etc. and use the enum instead for the comparison.

回答1:

That's because EL in its current version does not support accessing enums nor calling enum constants. This support is only available per EL 3.0.

It's unclear what your intent is, but it's good to know that you can compare enum properties as a String in EL. They are namely resolved as a String.

Assuming that you've a bean which look like this:

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

    private Status status;

    public Status getStatus() {
        return status;
    }
}

Then you could test the Status.FAILED condition as follows:

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

See also:

  • How to reference constants in EL?


回答2:

As BalusC indicated, you cannot access enums using EL, however, you can do this:

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

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

It would be ideal if bookingInformation.bookingStatus was an enum and not an int, but if re-factoring your app is out of the question due to its legacy nature, then my above example should help. You'd need a <c:set/> for each value of the enum (appears to just be two in your example).



回答3:

You have to import the enum class in your jsp page. As far as you import it then you can refer to it. I wrote an example below.

My enum is the 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;
    }
}

I have the websettings.jsp page that is uses a tag page etc.

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