Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 811
Zack Marrapese Avatar asked Jun 24 '10 20:06

Zack Marrapese


2 Answers

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>    
like image 90
BalusC Avatar answered Oct 31 '22 23:10

BalusC


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

like image 34
egbokul Avatar answered Oct 31 '22 23:10

egbokul