0
votes

I am working on a small E-commerce website,with spring boot for back-end purpose and trying to print product name and cost in row containing 4 cards.For this I am fetching all data using findAll() methods of JpaRepository and copied the first three data in another list and passed to webpage using model.addAttribute()

When I am running the program it works fine but when I am passing the URL which I have mapped I am getting this exception:

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

Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "threeproducts.productName" (template: "MyEcommerce" - line 89, col 40)

Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "threeproducts.productName" (template: "MyEcommerce" - line 89, col 40)

2020-08-10 20:57:52.433 ERROR 1152 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/MyEcommerce.html]")] with root cause

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'productName' cannot be found on object of type 'java.lang.String' - maybe not public or not valid?

What I know is we get this exception if model class not contain the property which we are trying to access in thymeleaf expression but in my model class property is there.

I am also posting necessary class and thymeleaf template below:-

Note: I am posting the part of thymeleaf template which contains code of grid and cards only.

If it is required to post the full code, then definitely I will. And also stackoverflow is giving me word restriction in post

Controller and service class:

Model class:

@Entity
@Table(name = "products")
public class Products {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int productId;
    private String productName;
    private String productCost;
    private String quantityAvailable;
}

Controller class:

@Controller
@RequestMapping("/www.shopping.com")           /*Just For Fun*/
public class CustomerController {

    @Autowired
    private CustomerServices customerServices;

    /*controller to show index page of website to customers*/
    @GetMapping("/IndexPage")
    public String ViewIndexPage(Model model)
    {
        List<Products> products= customerServices.ReturnThreeProducts();
        model.addAttribute("ListOfThreeProducts","products");
        return "MyEcommerce";
    }
}

Service class:

@Service
public class CustomerServices {

    @Autowired
    private CustomerRepository customerRepository;
    public List<Products> listofthreeproducts;

    public List<Products> ReturnThreeProducts()
    {
        List<Products> products=customerRepository.findAll();
       /* products.stream().forEach((productTemp) -> listofthreeproducts.add(productTemp));*/
        listofthreeproducts=products.subList(0,4);
        return listofthreeproducts;
    }
}

And in Last Thymeleaf template:

<body>
<--Code for navbar and jambotron upto here and below is of cards ignore 
images-->
<div class="container" th:each="threeproducts : ${ListOfThreeProducts}">
<div class="row">
    <div class="col-xl-3">
        <div class="card" style="width: 15rem;">
            <img class="card-img-top" src="..." alt="Card image cap" height="155">
            <div class="card-body">
                <h6 class="card-title" th:text = ${threeproducts.productName}></h6>
                <h6 class="card-text" th:text: $threeproducts.productCost></h6>
                <a href="#" class="btn btn-primary">AddToCard</a>
            </div>
        </div>
    </div>
    <!--<div class="col-xl-3">
        <div class="card" style="width: 15rem;">
            <img class="card-img-top" src="..." alt="Card image cap">
            <div class="card-body">
                <h6 class="card-title">Card title</h6>
                <h6 class="card-text">Price</h6>
                <a href="#" class="btn btn-primary">AddToCard</a>
            </div>
        </div>
    </div>
    <div class="col-xl-3">
        <div class="card" style="width: 15rem;">
            <img class="card-img-top" src="..." alt="Card image cap">
            <div class="card-body">
                <h6 class="card-title">Card title</h6>
                <h6 class="card-text">Price</h6>
                <a href="#" class="btn btn-primary">AddToCard</a>
            </div>
        </div>
    </div>
    <div class="col-xl-3">
        <div class="card" style="width: 15rem;">
            <img class="card-img-top" src="..." alt="Card image cap">
            <div class="card-body">
                <h6 class="card-title">Card title</h6>
                <h6 class="card-text">Price</h6>
                <a href="#" class="btn btn-primary">AddToCard</a>
            </div>
        </div>
    </div>-->
</div>
</div>
</body>

Thanks in advance...

Your words are value for me..

1
Public getter and setter for private String productName? also in your template syntax errors: th:text: $threeproducts.productCost -> th:text="$threeproducts.productCost" - Slava Ivanov
i forgot to mention getter and setter... - Atharva
@SlavaIvanov Sorry it does't work. - Atharva
Didn't work what? You need to be more specific to get help. As far as I understand you do have getters and setters and you just didn't copy them over into the code snippet in your description. Is this correct? Next, did you fix your syntax errors in the template? How did you fix it? Update the code snippet after the fix and error message, if it's different. The code th:text = ${threeproducts.productName} -> th:text =" ${threeproducts.productName}" - Slava Ivanov
@SlavaIvanov Sorry for my wrong accent, actually it working but only 50%(say), what output i am getting is only one card but expected is 4 and it is not printing data i.e,productName and cost instead of this it prints thymeleaf expression directly. - Atharva

1 Answers

0
votes

In your controller try:

model.addAttribute("ListOfThreeProducts", products);

No quotes around products. Currently you are putting the string literal 'products' into the model instead of the collection.