情報系学部生日記

備忘録や勉強したことのまとめ

KotlinとThymeleafの組み合わせで、Thymeleaf側でisHogeフィールドが参照できない。

ThymeleafとKotlinの組み合わせで発生した問題です。 コントローラからビューにisHogeという値を渡した場合に、 ビュー側のThymeleaf内でその値を使用するときisHogeという変数名で参照できないというものです。 これはKotlinのフィールドの概念を理解していればそんなに難しい内容でないのですが、 Kotlinで書いたコードがビルド後にどうなるかを意識していない場合に結構引っかかるのではないかと思います。

KotlinでisHogeというフィールドを書きコンパイルするとHogeというメンバ変数に対し、各アクセサが自動的に生成されるので Thymeleaf側からだとisHogeという変数は存在せずHogeという変数が見えるということですね。

それにしてもキャメルケースで書いた変数がパスカルケースになってしまうのは気持ちが悪いですね。 文章だけでは分かりにくいのでサンプルコードを載せておきます。 モデルは割愛します。

package com.example

import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.servlet.ModelAndView

@Controller
@RequestMapping("/books")
@Suppress("unused")
class BooksController(
    val service: BookService
){
    @GetMapping("/add")
    fun add() = ModelAndView("books/add")
}
package com.example

import org.springframework.stereotype.Service

@Service
class BookService{
    fun getBookList() = arrayListOf<Book>().apply {
        add(Book(1, "初めてのKotlin", 3000, false))
        add(Book(2, "初めてのJava", 2800, true))
        add(Book(3, "初めてのIntellij", 4500, false))
    }
}
package com.example

class Book(
    var id: Long,
    var title: String,
    var price: Long,
    var isRemoved: Boolean = false
)
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8"/>
    <title>Book List</title>
</head>
<body>
    <table>
        <tr>
            <th>ID</th>
            <th>Title</th>
            <th>Price</th>
            <th>IsRemoved</th>
        </tr>
        <tr data-th-each="book : ${bookList}">
            <td data-th-text="${book.id}"></td>
            <td data-th-text="${book.title}"></td>
            <td data-th-text="${book.price}"></td>
            <td data-th-text="${book.Removed}"></td>
            <!--<td data-th-text="${book.isRemoved}"></td>  isRemovedが参照できずエラーになる-->
        </tr>
    </table>
</body>
</html>