In JSP EL enum value always empty [duplicate]
Asked Answered
A

3

8

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.

Audriaaudrie answered 5/1, 2011 at 16:42 Comment(2)
#124098Bose
No it is not. I'm not having a problem with the condition but that then Enum object itself is not accessible, it is empty/null. It is as Tomcat would not see the Enum class at all.Audriaaudrie
B
17

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:

Burnell answered 5/1, 2011 at 16:46 Comment(7)
The problem is I'm comparing against an Integer, the ordinal value of the enum, not another enum. Can I convert an Integer to enum in EL?Audriaaudrie
Don't use ordinals. Use fullworthy enum values. Your getStatus() must return Status and not int. This is a sign of bad designed model. Ordinals are not constants. They may change whenever you add/remove/rearrange enum values. It sounds much like as if you're doing this as a (bad) workaround to be able to save Java enums in/from a database. This is a different subject then.Burnell
Reading your answer again, does that mean that I basically can't use a public enum class in EL?Audriaaudrie
No. EL doesn't support it. It only supports Javabeans as described in Javabeans spec. You could add a getter which returns all values of the status, but that's plain clumsy. You've got to solve this problem at a different level: i.e. don't use ordinals, but enums.Burnell
I'm fully aware that there should be an enum supplied but the situation is much more complicated that I could just change around unrelated class properties. This is part of a quite HUGE app.Audriaaudrie
It's not only enums. EL doesn't support accessing classes by full qualified classname nor accessing public static final constants and so on. But to say that EL sucks goes too far. This has simply never been the intent of EL. It's designed around the Javabeans spec. When you want to use non-Javabeans in EL, well... Best what you could to is to add another getter which does the desired job in the model.Burnell
I just believe EL's spec is going too far to limit you. Even worse, it encourages newbies to use scriptlets instead which are horrible because those do not limit them at all, slipping business logic into the JSPs. EE6 brings some new abilities to fix this, like function calls. Finally you will be able to access the non-javabeans conformant properties of the Java standard library!Audriaaudrie
C
7

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

Curlicue answered 8/1, 2011 at 18:20 Comment(0)
I
1

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>
Illuminate answered 26/4, 2016 at 20:1 Comment(1)
At the date the question was asked, this wasn't supported in EL. See also the currently accepted answer and the "See also" link thereof: https://mcmap.net/q/194973/-how-to-reference-constants-in-elBurnell

© 2022 - 2024 — McMap. All rights reserved.