0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Spring Boot + Thymeleaf + LombokでException evaluating SpringEL expression

Last updated at Posted at 2023-03-17

Spring徹底入門のチュートリアルをアレンジを加えながら進めていたところ、画面表示時にエラーとなったため、検証してみました。

環境

  • windowds 11
  • Java 17
  • Spring Boot 3.0.4
  • Spring 6.0.6
  • Thymleaf 3.1.1
  • STS 4

ソース抜粋

作成したソースは以下の通りです。
Spring徹底入門のチュートリアルではSpring Data JPAを使っていますが、MyBatisを使うようにしました。

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";
    }
}
RoomService.java
@Service
@Transactional
public class RoomService {
    @Autowired
    AvailableReservableRoomMapper reservableRoomMapper;

    public List<AvailableReservableRoom> findReservableRooms(LocalDate date) {
        return reservableRoomMapper.finbByReservedDate(date);
    }
}
AvailableReservableRoomMapper.java
@Mapper
public interface AvailableReservableRoomMapper {
    List<AvailableReservableRoom> finbByReservedDate(LocalDate reservedDate);
}
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>
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

検証

STSのコンソールを確認したところ、htmlに表示する際にフィールドが見つからない旨のエラーとなっている模様です。

エラーログ
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

結論

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

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

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

別のmodelクラスでアウトラインを見ていたところgettersetterがないことを確認

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

  1. jarをダブルクリック
    image.png
  2. 表示されたIDEsを選択し、Install / Update
    image.png
  3. SpringToolSuite4.iniに以下を追加し、STS再起動
SpringToolSuite4.ini
-vmargs -javaagent:lombok-1.18.26.jar

 

アウトラインを確認し、getterとsetterが追加されていることを確認

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?