3

I have generic class with this signature:

public abstract class EnumListBean<E extends Enum<E>> {

    public List<E> getEnumList() {
        //implementation details
    }

}

Currently I have to define a empty subclass in order to access the enumList property for a concrete generic parameter:

@ManagedBean
@ApplicationScoped
public class ItemRarityBean  extends EnumListBean<Item.Rarity>{
}

This makes its possible to access the property e.g:

<f:selectItems value="#{itemRarityBean.enumList}" var="rarity"
            itemLabel="#{rarity.readableName}" itemValue="#{rarity}" />

Im wondering whether one really have to declare a deriving bean but cant access the generic class as bean directly:

<f:selectItems value="#{enumListBean<Item.Rarity>.enumList}" var="rarity"
                itemLabel="#{rarity.readableName}" itemValue="#{rarity}" />
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Sebastian Hoffmann
  • 11,127
  • 7
  • 49
  • 77
  • You may find [OmniFaces ``](https://showcase-omnifaces.rhcloud.com/showcase/taghandlers/importConstants.xhtml) useful. – BalusC Jul 17 '12 at 19:03
  • In your specific case, it probably wouldn't be useful even if EL could access the concrete parameterised type. There is no way for `new EnumListBean.getEnumList()` to return anything else than `new EnumListBean.getEnumList()` without passing a type token because of type erasure. What you could do is fake an indexed property and have a bean indexable by a `Class` that returns the list of its values, but I'm not sure whether you can use class literals in EL. – millimoose Jul 17 '12 at 19:07
  • @BalusC Wow, nearly the exact thing i want to achieve. Can a `` imported enum even be used as list in conjunction with ``? – Sebastian Hoffmann Jul 17 '12 at 19:12
  • @BalsusC: Oh I just saw the first example. You might want to post this as an answere? – Sebastian Hoffmann Jul 17 '12 at 19:14

2 Answers2

4

You can't use generics in EL. EL is a runtime language based on reflection. You know, generics is only available during compiletime, not during runtime.

For your particular purpose, it's likely easier to use OmniFaces <o:importConstants>.

<o:importConstants type="com.example.Item$Rarity" var="Rarity" />
...
<h:selectOneMenu>
    <f:selectItems value="#{Rarity}" />
</h:selectOneMenu>

(the var attribute is not mandatory, but you'd otherwise need to reference it as #{Item$Rarity} which is not exactly nicely readable; if your Rarity enum were a standalone enum and not an inner enum, then you could just use type="com.example.Rarity")

It's by design treated as a Map<String, Rarity>, not a List<Rarity> or so. So if you intend to access the individual items in the var attribute of <f:selectItems>, so that you can access specific enum methods, then you'd need to explicitly iterate over Map#values() (which would require EL 2.2 support).

<h:selectOneMenu>
    <f:selectItems value="#{Rarity.values()}" var="rarity" itemValue="#{rarity}" itemLabel="#{rarity.readableName}" />
</h:selectOneMenu>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
2

Yes, you have to. Because instantiating abstract classes makes no sense.

fdreger
  • 12,264
  • 1
  • 36
  • 42