0

I have a problem list. Each problem has a sub category and main category and also each sub category has a main category. I want to list the problems like above.

--Main category1 (1 is id)
----subcat1
------problem1
------problem2
----subcat2
------problem3

--main category2
----subcat3
------problem4
------problem5
----subcat4
------problem6

and so on.

The html part is here;

    <ui:repeat  var="mainCatvar" value="#{dprEdit.mainCategories}">
    <h:outputText value="#{mainCatvar.mainCatName}" styleClass="mainTitle" /><br></br>  
            <ui:repeat var="subCategory" value="#{mainCatvar.subCategories}">
            <h:outputText value="#{subCategory.subCatName}" styleClass="title" />
                <h:selectManyCheckbox value="#{dprEdit.selectedProblems}"  >
                <f:selectItems value="#{subCategory.problems}" var="problem" 
                itemValue="#{problem.problemName}" itemLabel="#{problem.problemName}" />                                    
                </h:selectManyCheckbox>
            </ui:repeat>
    </ui:repeat>
<p:commandButton action="#{dprCreate.save}" value="Save" update="form1" ajax="false" style="width:150px" />

Here is my backend code;

    public class MainCatDAO extends BaseDAO {   
        private final static String SELECT_ALL_MAIN_CATEGORIES ="SELECT * FROM TESTAE.MAINCATPF";
        public MainCatDAO(Connection connection) {      
            super(connection);
        }
        private List<MainCat> getTable(String query, Object... values) throws ClassNotFoundException, SQLException {
            List<MainCat> table = new ArrayList<MainCat>();
            List<Map<String, Object>> data = this.getData(query, values);
            for (int i = 0; i < data.size(); i++) {
                ArrayList<SubCat> subList = new ArrayList<SubCat>();    
                // subList'i tekrardan tanımlama yani clear etmeme sebebim; maincat'a subList'i set etmeme rağmen,
                //sonrasında subList'i clear edince maincat'ın subList'i de sıfırlanıyor. 
                //Bu yüzden subList'i her seferinde tekrar tanımlıyorum.
                Map<String, Object> row = new HashMap<String, Object>();
                MainCat maincat = new MainCat();
                row = data.get(i);
                maincat.setMainCatId(((BigDecimal) row.get("MAINCATID")).intValue());
                maincat.setMainCatName(((String) row.get("MAINCATNAM")).trim());

                String sorgu = "SELECT * FROM TESTAE.SUBCATPF WHERE MAINCATID='"+((BigDecimal) row.get("MAINCATID")).intValue()+"'";            

                List<Map<String, Object>> dataSub = this.getData(sorgu);
                for (int a = 0; a < dataSub.size(); a++) {
                    ArrayList<Problem> problemList = new ArrayList<Problem>();
                    SubCat subcat = new SubCat();
                    row = dataSub.get(a);
                    if (row.get("SUBCATNAME") == null)
                        subcat.setSubCatName("");   
                    else
                        subcat.setSubCatName((((String) row.get("SUBCATNAME")).trim()));
                    subList.add(subcat);

                    String sorgu2 = "SELECT * FROM TESTAE.PROBLEMPF WHERE SUBCATID='"+((BigDecimal) row.get("SUBCATID")).intValue()+"'";
                    List<Map<String, Object>> dataProb = this.getData(sorgu2);
                    for (int p = 0; p < dataProb.size(); p++) {
                        Problem problem = new Problem();
                        row = dataProb.get(p);
                        Integer problemId = ((BigDecimal) row.get("PROBLEMID")).intValue();

                        if (row.get("PRBLMNAME") == null)
                            problem.setProblemName("");
                        else
                            problem.setProblemName((((String) row.get("PRBLMNAME")).trim()));
                        problemList.add(problem);
                    }
                    subcat.setProblems(problemList);
                }
                maincat.setSubCategories(subList);
                table.add(maincat);
            }
            return table;
        }

        public List<MainCat> getmainCategories () throws ClassNotFoundException, SQLException {

            return getTable(SELECT_ALL_MAIN_CATEGORIES);
    }}


Here is my save function;

            @ManagedBean(name = "dprEdit")
            @ViewScoped
            public class DprEdit implements Serializable {
            private List<String> selectedProblems = new ArrayList<String>();
    private List<MainCat> mainCategories;
    public DprEdit() throws ClassNotFoundException, SQLException {
    mainCategories = new MainCatDAO(ConnectionManager.getConnection()).getmainCategories();}

            public String save() throws ClassNotFoundException, SQLException, ParseException {
                    DprDAO dprDAO = new DprDAO(ConnectionManager.getConnection());


                    for (int i = 0; i < selectedProblems.size(); i++) {
                        dpr.setFormId(dpr.getFormId());
                        DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
                        Date today = new Date();
                        formDate = formatter.parse(formatter.format(today));
                    dpr.setFormDate(formDate);
                    dpr.setFilledBy(username);
                    dpr.setProblemName(selectedProblems.get(i));
                    String problemName = selectedProblems.get(i);
                    ProblemDAO problemDAO = new ProblemDAO(ConnectionManager.getConnection());
                    Problem prob = problemDAO.getProblemId(problemName);
                    dpr.setProblemId(prob.getProblemId());
                        dprDAO.insertDetail(dpr);
                    }
            public List<String> getSelectedProblems() {
                    return selectedProblems;
                }

            public void setSelectedProblems(List<String> selectedProblems) {
                    this.selectedProblems = selectedProblems;
                }
    public Integer getMaincatid() {
            return maincatid;
        }

        public void setMaincatid(Integer maincatid) {
            this.maincatid = maincatid;
        }}

My problem model attributes;

private Integer problemId;
private String problemName;
private String subCategory;
private String mainCategory;

my subcategory model attributes;

private Integer subCatId;
private String subCatName;
private List<Problem> problems;

my main category model attributes;

private Integer mainCatId;
private String mainCatName;
private List<SubCat> subCategories;

So, the problem is that I click some problems on the list then I click the save button and I expect to that selectedProblem list is full of my clicked problems. However the selectedProblems list is empty!

Do you have any advice?

Thank you all.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Armagan
  • 68
  • 9

1 Answers1

0

Look closer at <h:selectManyCheckbox value>, particularly at the associated bean.

<ui:repeat value="#{dprEdit.mainCategories}" var="mainCatvar">
    <ui:repeat value="#{mainCatvar.subCategories}" var="subCategory">
        <h:selectManyCheckbox value="#{dprEdit.selectedProblems}">
            <f:selectItems value="#{subCategory.problems}" />

Basically, you're binding the selected values of all checkbox groups to one and same bean property. During processing the form submit, every iteration will override the submitted values of checkbox group of the previous iteration. If you've placed a debug breakpoint on the setSelectedProblems() setter, you'd have noticed that. This way you ultimately end up with the submitted values of the last checkbox group. Given the "return null" complaint, apparently you selected nothing there.

This is definitely wrong. The <h:selectManyCheckbox value> should in some way be associated with the currently iterated #{subCategory}, not directly with the #{dprEdit} managed bean. One way is mapping it with #{subCategory} as key:

<h:selectManyCheckbox value="#{dprEdit.selectedProblems[subCategory]}">

With:

private Map<SubCat, String[]> selectedProblems = new HashMap<>();

Note that you can't use List<String> here as generic type information is erased during runtime and the default model value is String[] and there's no way of instructing JSF/EL otherwise. If you want to use a fixed type, you could consider moving the selectedProblems into SubCat so that you can keep using List<String>:

<h:selectManyCheckbox value="#{subCategory.selectedProblems}">
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Something has been changed thank you but it doesn't work correctly. selectedProblem.size() is always 15 which is the number of subcategories. There is a point that I cannot understand. I want to have a selectedProblem list like this ['problemname1', 'problemname2',....] but now my selectedProblem looks like ['subcat1', 'subcat2',....] I have a selectedProblem list So, is it okay to use SubCat model in Hashmap? – Armagan Jan 05 '15 at 11:48
  • Are you new to Java maps? The selected problems are just available as map value associated with subcategory as map key. Iterate over `selectedProblems.entrySet()` or `selectedOProblems.values()` to get them all (the latter however doesn't allow you to associate them with a subcategory while saving in the DB, nor did your initial approach ...). – BalusC Jan 05 '15 at 11:56
  • Sorry I could not explain correctly. Yes I have a map. The key of the map is a subcategory and the value of it is a list which consist of String. When I iterate it I can get all subcategories and its problems. But I want the selected ones (problems). By the way, yes I am new to Java map :) – Armagan Jan 05 '15 at 12:14
  • Hm? The selected ones are in that map. That "its problems" are the selected ones. – BalusC Jan 05 '15 at 12:23
  • No. Something goes wrong. Selected item is full of all subcategories. Do you have any idea? – Armagan Jan 05 '15 at 14:05
  • Yes, sure all map keys are filled. There's otherwise no way to find selected problems for each subcategory. Those keys do not represent selected problems. I am talking about map values. The selected problems are set as `List` map value associated with subcategory. You should explore the contents of that `List` for each subcategory. – BalusC Jan 05 '15 at 14:13
  • I missed something I am sorry. Thank you. You are right. I can reach the selected problems on the way you told. However, still I have a problem. Each item of selectedProblems.enrtySet() is entry and when I try to get value of entry, I use entry.getValue(). I suppose its type is a List but I get error which is "[Ljava.lang.String; cannot be cast to java.util.List". I can not figure casting out. I can not find any useful information about casting hasmap. Could you help me? – Armagan Jan 06 '15 at 09:20
  • Right, the eternal EL+Erasure problem, I should know better. I fixed the answer. – BalusC Jan 06 '15 at 09:40
  • It works! Thank you but I pass the itemValue "problemName" but my values come like this "com.myproject.srm.model.Problem@2df0f8d3". How can I get my problems' name? – Armagan Jan 06 '15 at 11:45
  • Use `` the way you did. My answer just contains the minimal snippet needed to solve the problem as described in the question. – BalusC Jan 06 '15 at 11:48
  • Okey I will figure out. Thank you very much! – Armagan Jan 06 '15 at 14:03