When I access a variable in a -tag it is working fine and give me [] because ists an empty List. If I try to access it the same way in a th:field it leads to a NotReadablePropertyException:
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'votes.get(1)' of bean class [foo.ChangeVotesForm]: Bean property 'votes.get(1)' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
I cant figure out why it is working in a a-tag and not in the field. Because both should do votes.get(1)... And I tried voteValues = List and voteValue = Integer both with the same Result.
Any Idea whats wrong here? And how to fix this?
I have the following:
Form:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Validated
public class ChangeVotesForm {
    private Map<Integer, Map<Integer, List<Vote>>> votes;
    private Map<Integer, Map<Integer, List<Item>>> dataMap;
}
Vote:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "vote")
public class Vote {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private int id;
    @ManyToOne(fetch = FetchType.LAZY)
    private Item item;
    @ElementCollection
    @Builder.Default
    private List<Integer> voteValues = new ArrayList<>();
    @Column(length = 2000)
    private String detailedValue;
}
Item:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "item")
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private int id;
    private int block;
    private int subblock;
    private Question question;
}
Question:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "question")
public class Question {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private int id;
    @Column(name = "TOPICSTRING", length = 2000)
    private String topicString;
    @OneToMany
    private List<Answer> answers;
}
Answer:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "answer")
public class Answer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private int id;
    private String answertext;
}
Controller:
@GetMapping("/")
public String index(Model model, Authentication auth) {
    ChangeVotesForm form = ChangeVotesForm.builder().votes(ChangeVotesForm.getVotesList(this.votesService.createVotesList())).dataMap(ChangeVotesForm.getDataList(this.itemsService.getItems())).build();
    //Just getting all Questions and Answers from the DB and put them in die Form object grouptBy Block / Subblock
    model.addAttribute("form", form);
    model.addAttribute("view", "feedbackItems");
    }
    return "index";
}
Template:
<div th:fragment="feedbackItems" id="content"
    xmlns:th="http://www.w3.org/1999/xhtml">
    <div class="row flex-fill">
        <div class="col-8 d-flex flex-column">
            <div class="form-group" th:each="blockEntry, blockIndex : *{dataMap}">
                <div th:each="subBlockEntry, subBlockIndex : ${blockEntry.value}">
                    <div th:each="item, itemIndex : ${subBlockEntry.value}">
                        <a th:utext="${item.question.topicString}"></a>
                        <ul>
                            <li th:each="answer : ${item.question.answers}">
                                    <a th:text="*{votes.get(__${item.getBlock()}__).get(__${item.getSubblock()}__)[__${itemIndex.index}__].voteValues}"></a>
                                    <!-- a-tag is working fine and is [] -->
                                    <!-- the following leads to the Exception -->
                                    <input type="radio"
                                            th:field="*{votes.get(__${item.getBlock()}__).get(__${item.getSubblock()}__)[__${itemIndex.index}__].voteValues}"
                                            th:value="${answer.id}" />
                                    <label th:for="${answer.id}"
                                        th:text="${answer.answertext}"></label>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
Update:
If I change the Map<Map<List<>>> to List<> it works fine. Example: like above only ChangeVotesForm:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Validated
public class ChangeVotesForm {
    private List<Vote> votes;
    private Map<Integer, Map<Integer, List<Item>>> dataMap;
}
And in the Template:
<div th:fragment="feedbackItems" id="content"
    xmlns:th="http://www.w3.org/1999/xhtml">
    <div class="row flex-fill">
        <div class="col-8 d-flex flex-column">
            <div class="form-group" th:each="blockEntry, blockIndex : *{dataMap}">
                <div th:each="subBlockEntry, subBlockIndex : ${blockEntry.value}">
                    <div th:each="item, itemIndex : ${subBlockEntry.value}">
                        <a th:utext="${item.question.topicString}"></a>
                        <ul>
                            <li th:each="answer : ${item.question.answers}">
                                    <input type="radio"
                                            th:field="*{votes[__${itemIndex.index}__].voteValues}"
                                            th:value="${answer.id}" />
                                    <label th:for="${answer.id}"
                                        th:text="${answer.answertext}"></label>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
Whats the problem with thymeleaf and Maps? The Map Values are generated, so just take multiple Lists in the form wouldn`t be a real solution.