How to access enum properties in EL?
Asked Answered
L

2

17

Given the following enum.

public enum Constants
{
    PAGE_LINKS(10);
    //Other constants as and when required.

    private final int value;

    private Constants(int value){
        this.value = value;
    }

    public int getValue(){
        value;
    }    
}

This enum is placed under an application scoped bean like so,

@ManagedBean
@ApplicationScoped
public final class ConstantsBean
{
    private Constants constants;

    public ConstantsBean() {}

    public Constants getConstants() {
        return constants;
    }
}

How to access the value of PAGE_LINKS in EL?

<p:dataGrid pageLinks="#{}".../>

What should be written in #{}? Is it possible?


EDIT:

Modifying the bean in the following way,

@ManagedBean
@ApplicationScoped
public final class ConstantsBean
{
    public ConstantsBean() {}

    public int getValue(Constants constants) {
        return constants.getValue();
    }
}

and then accessing in EL like so,

<p:dataGrid pageLinks="#{constantsBean.getValue('PAGE_LINKS')}".../>

somehow works but I don't believe in this ugly way.

Lordly answered 17/4, 2014 at 3:2 Comment(2)
#{constantsBean.constants.value} should work for you.Trundle
That doesn't work, @SazzadurRahamanLordly
H
20

This, as commented by Sazzadur,

#{constantsBean.constants.value}

should work. Your enum has a proper public getter for its value property. However, you should also make sure that you set the constants property of the managed bean to the desired enum value. You namely didn't do that in the code snippet posted so far and thus it remains null. EL does by design not print anything when a (base) property is null.

Here's how you could set it:

@ManagedBean
@ApplicationScoped
public final class ConstantsBean {
    private Constants constants = Constants.PAGE_LINKS;

    public Constants getConstants() {
        return constants;
    }
}

I'd however rename the property (and getter) to pageLinks for better self-documentability.

#{constantsBean.pageLinks.value}

An alternative is to use OmniFaces <o:importConstants>, based on your question history you're already familiar with OmniFaces and probably also already using it in your current project.

<o:importConstants type="com.example.Constants" />
...
#{Constants.PAGE_LINKS.value}

This way you don't need to wrap the thing in an application scoped bean.

Haunch answered 25/4, 2014 at 16:5 Comment(14)
<o:importConstants> cannot find a given type. I followed this answer and moved the Constants class (enum actually) to /WEB-INF/classes/util/Constants.java from /src/java/util/Constants.java. The IDE says, "Incorrect package". This tag (inside <h:form>), <o:importConstants var="const" type="util.Constants"/> throws java.lang.IllegalArgumentException: Cannot find type 'util.Constants' in classpath. What obvious am I missing?Lordly
What IDE are you using? It should automatically compile the .java file from /src and put the created .class file in /WEB-INF/classes. You should not ever have the need to manually fiddle around in /WEB-INF/classes. Perhaps you accidently turned off automatic building?Haunch
It is NetBeans IDE 8.0. What I did was : undeployed the application from the server (GlassFish 4.0), restarted the server, did clean and build and then deployed the application from all over again the scratch but the same exception then after remained. All Java packages are stored under /src/java. The Constants class is also there in /src/java/util/Constants.java and it is available in the build folder - /build/web/WEB-INF/classes/util/Constants.class. It should automatically be available to the deployed WAR then.Lordly
This is the full path of the Constants.class (an enum) after the application is deployed - E:\Project\JavaEE\Project\Project-war\build\web\WEB-INF\classes\util\Constants.classLordly
To exclude the one and other, did the actual answer work for you?Haunch
Yes one with the @applicationScoped works. I forgot to assign Constants.PAGE_LINKS to private Constants constants in the managed bean but I liked the OmniFaces way. I don't know why it cannot get the enumLordly
As a test, can you in a backing bean class (e.g. post construct or action method) execute the following lines without exceptions? Class.forName("util.Constants"); and Class.forName("util.Constants", true, Thread.currentThread().getContextClassLoader());.Haunch
Yes both of them are successful in a method annotated by @PostConstruct in a managed bean. (On the contrary, I have tried giving a non-existent class to Class.forName() like Class.forName("aaa.bbb") and they failed with java.lang.ClassNotFoundException as obvious).Lordly
Okay, where is the OmniFaces JAR placed? It must be in /WEB-INF/lib of the deployment, not elsewhere in the classpath.Haunch
The OmniFaces jar is placed under /WEB-INF/lib as other libraries. It does other functions somewhere else in the application.Lordly
Sorry, this got me baffled. It should just work. Only thing which I haven't tried is Netbeans, but that should hardly be the cause. Are you absolutely positive that you didn't make a typo in type attribute? I have the impression that you're actually not using the same FQN as you've posted here as util.Constants, as you started to mention aaa.bbb.Haunch
I looked into the qualified name very carefully. There is no typo in the type attribute. (Yes the enum name was changed after this post. It is actually util.IntegerConstants. I used this name everywhere including Class.forName() as a test case in the previous comments.) The class complies correctly. So, it should not be related to the NetBeans IDE.Lordly
I have just upgraded OmniFaces from 1.6.3 to 1.7 and the problem vanished into thin air without any other modifications. Thank you!Lordly
That's great, but I can't explain that. The only 1.6.3 -> 1.7 change which was made in <o:importConstants> is that the constants are stored in an ordered map instead of an unordered map, but that step is beyond finding the type in the classpath which has not changed.Haunch
G
10

Since Primefaces 6.0 you can also use PrimeFaces importEnum (Before that import was in "Primefaces Extensions").

https://www.primefaces.org/showcase/ui/misc/importEnum.xhtml

Gilford answered 30/4, 2014 at 11:30 Comment(4)
since it is not mentioned in the example above: xmlns:pe="http://primefaces.org/ui/extensions" is the proper namespace to includeObscurantism
and you need to add the extension to the classpath: https://mcmap.net/q/744398/-using-primefaces-extensions-inputnumber and github.com/primefaces-extensions/…Obscurantism
unfortunately code completion in Eclipse Kepler with JBoss Tools does not work and I found no Eclipse plugin that would support it. But nothing is perfect :-) and it's still better than writing @Name enum Foo { xxx, bar ; public static String getXxx() { return xxx.name(); } ... } getters and exposing the enum to the client (using it ala #{foo.xxx}) for me.Obscurantism
The link is dead since importEnum has been incorporated into PF as of 6.1Molding

© 2022 - 2024 — McMap. All rights reserved.