stacker
stacker

Reputation: 177

problem with iterate over java.util.Map using "JSF" OR JSTL TAGS

I'm using Richfaces JSF and I want to iterate over an Map<Object,Object>. I see many examples on Sun forums and other sites but in my case it doesn't work. Here is my XHTML code:

<c:forEach items="#{order.customOptions}" var="option">
    <h:outputText value="this text does not print" />
    <h:outputText value="#{option.value.name}" />
    <h:outputText value="#{option.value.key}" />
</c:forEach>

The "order" object is of type Order. The "customOptios" is of type Map<CustomOption,CustomOptionValue>. When I create an Javascript alert on to print '#{order.customeOptions}' its content is correct, but it does not even enter in c:forEach loop.

Update 1:: I tried a list but it doesn't work. I used list and got answer in other pages. I also use a4j:poll and some other ajax component is there any problem with them?

<c:forEach items="#{order.food.cusomableOptions}" var="option">
    <h:outputText value="this text does not print" />
    <h:outputText value="#{option.title}" />
</c:forEach>

Update 2: Here is output of <h:outputText value="#{order.customOptions}" />:

{model.CustomOption@be8464=model.CustomOptionValue@14e8ac9, 
 model.CustomOption@1ea0c8b=model.CustomOptionValue@78f4, 
 model.CustomOption@24389c=model.CustomOptionValue@3f0bc0, 
 model.CustomOption@a765c=model.CustomOptionValue@3b34ca, 
 model.CustomOption@95868c=model.CustomOptionValue@199de59}

Update 3: when I use it outside of rich:column it works, but when I use it in a rich:dataTable and rich:column tag it doesn't work:

<rich:column>
    <f:facet name="header">
        <h:outputText value="xf" />
    </f:facet>
    <c:forEach items="#{order.customOptions}" var="option">
        <p><h:outputText value="option : #{option.key.title}" /></p>
    </c:forEach>
</rich:column>

Upvotes: 2

Views: 10012

Answers (7)

marioosh
marioosh

Reputation: 28556

If i need to iterate over Map, i use helper class (for example Entry) like below:

public class Entry {
    private String value;
    private String key;

    public Entry(String value, String key) {
        super();
        this.value = value;
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

and method that convert map to List:

private List<Entry> mapToList(Map<String,String> map) {
    List<Entry> list = new ArrayList<Entry>();
    for(String key: map.keySet()) {
        list.add(new Entry(key, map.get(key)));
    }
    return list;        
}

xhtml:

<ui:repeat var="entry" value="#{bean.list}" varStatus="i">
    <div>#{entry.key} : #{entry.value}</div>
</ui:repeat>

Maybe that will help You... or maybe not ;)

Upvotes: 3

BalusC
BalusC

Reputation: 1108722

JSTL and JSF doesn't work seamlessly together in sync as you would intuitively expect from the ordering in the source code. Roughly said, JSTL processes the entire page from top to bottom first and then hands the generated output (thus, without any JSTL tags, but with its generated output) over to JSF which in turn processes the entire page from top to bottom again.

JSF UIData components like h:dataTable and rich:dataTable haven't generated any rows yet at the moment JSTL runs, which cauces that you won't see anything from c:forEach inside a column.

To fix this, you should rather use the JSF-supplied iterating components, such as RichFaces' a4j:repeat, or Facelets' ui:repeat, or Tomahawk's t:dataList. They all do less or more the same as the JSTL c:forEach.

For the remnant of JSTL tags, only the functions taglib is useful in JSF, all the other taglibs are superflous in a JSF environment since it either provides the same functionality out of the box (JSTL core and format taglibs), or it simply doesn't suit in the MVC ideology (JSTL sql and xml taglibs).

Upvotes: 1

Billy Bob Bain
Billy Bob Bain

Reputation: 2895

You should use an equivalent JSF tag. Have you tried <a4j:repeat/>?

Upvotes: 0

Shervin Asgari
Shervin Asgari

Reputation: 24499

Just convert your MAP to a ArrayList, and use h:dataTable and your problem should be solved.

Upvotes: 0

ATorras
ATorras

Reputation: 4303

Maybe you should not mix JSTL:core tags and JSF:h tags.

Regards.

Upvotes: 0

Michael Borgwardt
Michael Borgwardt

Reputation: 346300

If the loop is not even entered, that indicates that the map is simply empty.

You could diagnose that by putting something like

<h:outputText value="map size: #{order.customOptions.size()}" />

in front of the loop tags, but you should really set up an IDE like eclipse or Netbeans and run your code within it so that you can use a real debugger - you'll be able to pin down the problem much easier and quicker that way.

Upvotes: 1

Vincent Ramdhanie
Vincent Ramdhanie

Reputation: 103135

This blog might be helpful as there are some issues when using JSTL tags on JSF.

Upvotes: 4

Related Questions