JSF2: limiting cc:attribute to a given object type within a List
If I had a managed bean as follows:
@ManagedBean
@RequestSchoped
public class Example {
private List<String> stringList;
private List<Long> longList;
// getters, setters, etc. down here
}
and had a custom component which accepted a List as an attribute:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="aList" type="java.util.List" />
</cc:interface>
<cc:implementation>
<!-- code is in here -->
</cc:implementation>
</html>
How could I make sure that this worked:
<myComp:previousComponent aList="#{example.stringList}" />
but this didn't:
<myComp:previousComponent aList="#{example.longList}" />
In other words, what I want to do for the cc:attribute开发者_开发百科
is as follows:
<cc:attribute name="aList" type="java.util.List<java.lang.String>" />
However, as we know xhtml doesn't take kindly to using > or <. Also, with Generics only being checked at compile time, I'm not sure how this would be done. Does anyone know if this is possible?
You could check the type of each item using #{item.class.name}
. The Class#getName()
returns a String
denoting the type. E.g. java.lang.String
or java.lang.Long
. You could make use of it in the rendered
attribute.
Add an extra attribute denoting the full qualified classname.
<my:comp list="#{bean.list}" type="java.lang.String" />
in combination with
<cc:attribute name="list" type="java.util.List" required="true" />
<cc:attribute name="type" type="java.util.String" required="true" />
and this logic in cc:implementation
:
<ul>
<ui:repeat value="#{cc.attrs.list}" var="item">
<h:panelGroup rendered="#{item.class.name == cc.attrs.type}">
<li>#{item}</li>
</h:panelGroup>
</ui:repeat>
</ul>
If you are the one producing these lists then the following could be a trivial solution:
interface StringList extends List<String> {}
class ArrayStringList extends ArrayList<String> implements StringList {}
Not too elegant though.
I think we have reached the boundaries of the Java language here. I have encountered the same problem, and couldn't find a better solution either...
精彩评论