views:

1045

answers:

2

Hello

I hope you can help me. I'm new to java and jsf and richfaces and I've created a java map in a class (called "TaskListData") accessed by my backing bean as follows:

    public class TaskListData {
    private Map<String, String[]> srcMasks = new HashMap<String, String[]>();
    private Map<Integer, Map<String, String[]>> ftqSet = new HashMap<Integer, Map<String, String[]>>();

public void setFTQSet(Integer ftqid, String[] src, String[] masks) {  
        srcMasks.put("srcDir", src);
        srcMasks.put("masks", masks);
        ftqSet.put(ftqid, srcMasks);
    }

this ftqSet fits in below roughly translating to this (perlism) overall datastructure:

feedId = "5",
feedName = "myFeedName",
ftqSet => {
            1 => {
                    srcDirs = ["/path/string"],
                    masks = ["p.txt", "q.csv"]
                 }
            2 => { ...
                 }
          }, ...

of which there will be multiple records of the above. I had been returning an ArrayList String when the structure only stored feedId and feedName, but now I've tacked on this hash of hashes of arrays I don't think I can do that any more and an object of type TaskListData seems more appropriate (although probably not right).

My questions a) what should the return type of my backing bean method be? b) in my test jsf index.jsp file i've been trying to access some of the data using

<c:forEach items="#{MyBacking.feedDataList}" var="f">
                    <h:outputText value="this text does not print" />
                    <h:outputText value="${f.feedId}" />
                </c:forEach>

but it's only outputting the first outputText not the second. Why would this be? Once I've passed the correct return type, (c) how would I access this structure's individual elements so I can create a nice table?

btw, Don't mention rich:dataList, I've been yarning about why that didn't work for me in the jboss forum. i'm up for using the core tags for this one.

Any help massively, massively appreciated. Mark

+2  A: 

Each iteration of Map in a c:forEach gives a Map.Entry instance which in turn has getKey() and getValue() methods. It's similar to doing for (Entry entry : map.entrySet()) in plain Java.

E.g.

<c:forEach items="#{bean.map}" var="entry">
    <h:outputText value="Key: #{entry.key}, Value: #{entry.value}" /><br />
</c:forEach>

In case of a Map<Integer, Map<String, String[]>> the #{entry.value} returns a Map<String, String[]>, so you need to iterate over it as well:

<c:forEach items="#{bean.map}" var="entry">
    <h:outputText value="Key: #{entry.key}, Values:" />
    <c:forEach items="#{entry.value}" var="nestedentry">
        <h:outputText value="Nested Key: #{nestedentry.key}, Nested Value: #{nestedentry.value}" />
    </c:forEach><br />
</c:forEach>

But in your case, the #{nestedentry.value} is actually a String[], so we need to iterate over it again:

<c:forEach items="#{bean.map}" var="entry">
    <h:outputText value="Key: #{entry.key}, Values:" />
    <c:forEach items="#{entry.value}" var="nestedentry">
        <h:outputText value="Nested Key: #{nestedentry.key}, Nested Values: " />
        <c:forEach items="#{nestedentry.value}" var="nestednestedentry">
            <h:outputText value="#{nestednestedentry}" />
        </c:forEach><br />
    </c:forEach><br />
</c:forEach>

By the way, this ought to work with rich:dataList as well.

BalusC
BalusC this will prove v helpful thanks.
Mark Lewis
A: 

The example really helped me out. However I'm really stuck again. Is there a way you can put a value to a Map or List ?

Given the below snippet that draws a number of listboxes (the number is determined dynamically at run time):

<c:forEach var="bepUnDimDefIndex" begin="0" end="#{searchBinDimRelDefActionBean.dimRelDef.aantalBepUnDimDefs - 1}">
<c:set var="unDimDefSid" value="#{searchBinDimRelDefActionBean.dimRelDef.bepUnDimDefs[bepUnDimDefIndex].sid}" />
<c:set var="unDimDefDisplayNaam" value="#{searchBinDimRelDefActionBean.dimRelDef.bepUnDimDefs[bepUnDimDefIndex].displayNaam}" />

<ice:outputLabel value="#{unDimDefDisplayNaam}" />

<ice:selectOneListbox id="#{unDimDefSid}" value="#{addBinDimRelActionBean.mapOfSelectedUnDims}">
<f:selectItems  value="#{addBinDimRelActionBean.mapOfUnDimSelectItems[unDimDefSid]}" />
</ice:selectOneListbox>                                     
</c:forEach>

That code works fine upon first display. The values for each listbox get retrieved ok and the listboxes display correctly with the correct values taken from the backing map: this is done with the below snippet (taken from the above snippet):

<f:selectItems  value="#{addBinDimRelActionBean.mapOfUnDimSelectItems[unDimDefSid]}" />

However, the code to "put" the value the user selected into the backing map/list doesn't seem to work. As you can see from the first snippet I'm trying to do that via

<ice:selectOneListbox id="#{unDimDefSid}" value="{addBinDimRelActionBean.mapOfSelectedUnDims[unDimDefSid]}">.

But I get a

javax.faces.el.PropertyNotFoundException: javax.el.PropertyNotFoundException: /WEB-INF/pages/tax/dimensie/binair/beheer/tax-dimensie-binair-manage.xhtml @28,115 value="#{addBinDimRelActionBean.mapOfSelectedUnDims[unDimDefSid]}": Target Unreachable, 'mapOfSelectedUnDims' returned null.

Is it not possible to put a value to a map/list ? If it is possible what's the best way to do this, given that my set of listboxes is calculated dynamically ?

Thanks, EDH

Edwin
BalusC