Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

spring boot An error happened during template parsing

@Controller
@RequestMapping("/products")
public class ProductsController {
    @Autowired
    private ProductsRepository repo;

    @GetMapping({"", "/"})
    public String showProductList(Model model) {
        List<Product> products = repo.findAll(Sort.by(Sort.Direction.DESC, "id"));
        model.addAttribute("products", products);
        return "products/index";
    }
}
//properties
spring.application.name=beststore
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/beststore
spring.datasource.username=root
spring.datasource.password=9874156R
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
resources/static/index.html

<body>
<div class="container">
  <h1 class="text-center my-4">Welcome to our website</h1>

  <a class="btn btn-primary" href="/products">Products</a>
</div>

resources/templates/products/index.html

<body>
<div class="container">
    <h1 class="text-center my-4">Products</h1>

    <a class="btn btn-primary" href="/products/create">Create Product</a>

    <table class="table">
        <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Brand</th>
            <th>Category</th>
            <th>Price</th>
            <th>Image</th>
            <th>Create At</th>
            <th>Action</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="product : ${products}">
            <td th:text="${product.id}"></td>
            <td th:text="${product.name}"></td>
            <td th:text="${product.brand}"></td>
            <td th:text="${product.category}"></td>
            <td th:text="${product.price} + '$'"></td>
            <td>
                <img th:src="@{'/images/' + ${product.imageFilename}}" alt="..." width="100">
            </td>
            <td th:text="${#dates.format(product.createdAt, 'yyyy-MM-dd')}"></td>
            <td style="white-space: nowrap">
                <a class="btn btn-primary btn-sm" th:href="@{/products/edit(id=${product.id})}">Edit</a>
                <a class="btn btn-danger btn-sm" th:href="@{/products/delete(id=${product.id})}"
                   onclick="return confirm('Are you sure?')">Delete</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>

there is no problem when i open http://localhost:8080 i can get index page but when i click products button i get redirected to http://localhost:8080/products and there is this error

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Wed Jan 15 13:53:26 AZT 2025

There was an unexpected error (type=Internal Server Error, status=500).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

An error happened during template parsing (template: "class path resource [templates/products/index.html]")

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/products/index.html]")

Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "product.id" (template: "products/index" – line 31, col 17) at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393) at org.attoparser.MarkupParser.parse(MarkupParser.java:257) at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) … 48 more

Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "product.id" (template: "products/index" – line 31, col 17)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field ‘id’ cannot be found on object of type ‘com.example.beststore.Model.Product’ – maybe not public or not valid?

>Solution :

You have it written in stacktrace —

Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "product.id"

On your object product is probably id not accessible as property, and that is correct, correct way is to use getter/setters. So replace all accessors to properties with getters and it should be ok.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading