Spring Boot + Thymeleaf + LombokでException evaluating SpringEL expression

[Spring徹底入門](https://www.shoeisha.co.jp/book/detail/9784798142470)のチュートリアルをアレンジを加えながら進めていたところ、画面表示時にエラーとなったため、検証してみました。

# 環境
- windowds 11
- Java 17
- Spring Boot 3.0.4
- Spring 6.0.6
- Thymleaf 3.1.1
- STS 4

# ソース抜粋
作成したソースは以下の通りです。
[Spring徹底入門](https://www.shoeisha.co.jp/book/detail/9784798142470)のチュートリアルではSpring Data JPAを使っていますが、MyBatisを使うようにしました。
```java:RoomsController.java
@Controller
@RequestMapping("rooms")
public class RoomsController {
    @Autowired
    RoomService roomService;

    @RequestMapping(method = RequestMethod.GET)
    String listRooms(Model model) {
        LocalDate today = LocalDate.now();
        List<AvailableReservableRoom> rooms = roomService.findReservableRooms(today);
        model.addAttribute("date", today);
        model.addAttribute("rooms", rooms);
        return "room/listRooms";
    }
}
```
```java:RoomService.java
@Service
@Transactional
public class RoomService {
    @Autowired
    AvailableReservableRoomMapper reservableRoomMapper;

    public List<AvailableReservableRoom> findReservableRooms(LocalDate date) {
        return reservableRoomMapper.finbByReservedDate(date);
    }
}
```
```java:AvailableReservableRoomMapper.java
@Mapper
public interface AvailableReservableRoomMapper {
    List<AvailableReservableRoom> finbByReservedDate(LocalDate reservedDate);
}
```
```java:AvailableReservableRoom.java
import lombok.Data;

@Data
public class AvailableReservableRoom {
    private Integer roomId;
    private LocalDate reservedDate;
    private String roomName;
}
```
```AvailableReservableRoomMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mrs.domain.mapper.AvailableReservableRoomMapper">
    <resultMap id="availableReservableRoomMap"
        type="mrs.domain.model.AvailableReservableRoom">
        <result column="room_id" jdbcType="INTEGER" property="roomId" />
        <result column="reserved_date" jdbcType="DATE" property="reservedDate" />
        <result column="room_name" jdbcType="VARCHAR" property="roomName" />
    </resultMap>
    <select id="finbByReservedDate" parameterType="java.time.LocalDate" resultMap="availableReservableRoomMap">
        select
            t1.reserved_date,
            t1.room_id,
            t2.room_name
        from
            reservable_room t1,
            meeting_room t2
        <where>
                t1.room_id = t2.room_id
            and t1.reserved_date = #{reservedDate}
        </where>
        order by room_id
    </select>
</mapper>
```
```html:listRooms.html
<ul>
    <li th:each="room: ${rooms}">
        <a th:href="@{'/reservations/' + ${date} + '/' + ${room.roomId}}"
           th:text="${room.roomName}"></a>
    </li>
</ul>
```
# 画面表示
Spring Bootを起動し、http://localhost:8080/rooms にアクセスすると以下のエラーとなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289096/266d19d8-d29a-4d3c-ffab-693ed7040e98.png)
# 検証
STSのコンソールを確認したところ、htmlに表示する際にフィールドが見つからない旨のエラーとなっている模様です。
```txt:エラーログ
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "room.roomId" (template: "room/listRooms" - line 15, col 12)
	at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:292) ~[thymeleaf-spring6-3.1.1.RELEASE.jar:3.1.1.RELEASE]
	at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166) ~[thymeleaf-3.1.1.RELEASE.jar:3.1.1.RELEASE]
	at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66) ~[thymeleaf-3.1.1.RELEASE.jar:3.1.1.RELEASE]
～
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'roomId' cannot be found on object of type 'mrs.domain.model.AvailableReservableRoom' - maybe not public or not valid?
	at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217) ~[spring-expression-6.0.6.jar:6.0.6]
	at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104) ~[spring-expression-6.0.6.jar:6.0.6]
	at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:405) ~[spring-expression-6.0.6.jar:6.0.6]
```

Controllerで確認すると値は設定されているように見えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289096/a96313b3-7679-2b85-757d-17e041e0000e.png)

# 結論
~~lombokの`@Data`で端折っていた`getter/getter`を自前で定義するように修正したら画面表示できました。~~

~~Lombokにお任せしたGetterではThymleafでフィールドの参照ができなそうです。~~
~~(なお、Lombokで生成されたソースまでは確認しておりません)~~

よくよく調べた結果、どうやらLombokのインストールがうまくいっていなかった模様・・・

別のmodelクラスでアウトラインを見ていたところ`getter`と`setter`がないことを確認
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289096/d0fd30f0-b1ee-fa30-231c-baa2cbf35ed5.png">

Lombokのインストールが必要という情報を見つけたため試してみました(以前使用したときはやった記憶がない・・・)
手順は以下

1. jarをダブルクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289096/e999c8f1-88d2-3704-c970-3832dceceb7f.png)
1. 表示されたIDEsを選択し、`Install / Update`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289096/7bf4c6a4-c94f-07d3-cf0d-4039f070a4e5.png)
1. SpringToolSuite4.iniに以下を追加し、STS再起動
```SpringToolSuite4.ini
-vmargs -javaagent:lombok-1.18.26.jar
```
   　

アウトラインを確認し、getterとsetterが追加されていることを確認
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289096/75027bb6-e805-5925-e030-1582ddf2ecf5.png">

以前このような手順をやった記憶がなかったため
ThymleafでLombokの自動生成メソッドが参照できないのが原因だと思い込んでいましたが
Lombokのインストールが必要だったというオチでした(すみません・・・)。