javaspringspring-bootthymeleafspring-thymeleaf

springBoot + Thymeleaf: read value with Lombok


I have this bean:

@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BlogSearchDataPayload {

    String langCode;
    String blogCategory = BlogCategoryEnum.all.name();


}

the controller:

  @GetMapping({"/blogs", "/"})
    public String index(@RequestParam(name = "langCode", required = false) String langCode,
                        @RequestParam(name = "blogCategory", required = false) String blogCategory,
                        final ModelMap model) throws ExecutionException, InterruptedException {

        model.addAttribute("blogItems",
                blogItems(langCode, blogCategory, null, null));
        model.addAttribute("searchFilter", BlogSearchDataPayload.builder());

        return "blogs";
    }

and the template:

<select name="blogCategory" th:field="*{searchFilter.blogCategory}" th:id="blogCategory" onchange="updateAction()">
                    <option value="all">All</option>
                    <option value="transits">Transits</option>
                    <option value="natalchart">Natal Chart</option>
                    <option value="solarreturn">Solar Return</option>
                    <option value="synastry">Synastry</option>
                </select>

but I have this error:

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'blogCategory' of bean class [com.mysticriver.web.payload.BlogSearchDataPayload$BlogSearchDataPayloadBuilder]: Bean property 'blogCategory' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:627)
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:617)

Solution

  • Maybe you have used the builder wrongly. The builder shouldn't use like that.

    In short, you can fix like this:

    @GetMapping({"/blogs", "/"})
    public String index(@RequestParam(name = "langCode", required = false) String langCode,
                        @RequestParam(name = "blogCategory", required = false) String blogCategory,
                        final ModelMap model) throws ExecutionException, InterruptedException {
    
            model.addAttribute("blogItems", blogItems(langCode, blogCategory, null, null));
            model.addAttribute("searchFilter", new BlogSearchDataPayload());
            return "blogs";
    
    }
    

    Further explain, you should use builder whenever you want to create the object with an arbitrary params. For example, the class Cat may have a lot of fields (color, voice, eye, fur, etc) and creating constructor for it is very difficult (due to many combinations). In that case, the class CatBuilder should be used as follow:

    private getMyCat() {
        Cat cat = Cat.builder()
                     .color("Yellow")
                     .eye("Blue")
                     .build();
        return cat;
    }