Currently, I'm following a Spring Boot course. However, since yesterday, I'm facing this issue when I launch my main class through VS Code: "Field pr in com.training.training.Service.ProduitServiceImpl required a bean of type 'com.training.training.Repos.ProduitRepository' that could not be found." So I'm asking for some help to troubleshoot this problem.
Here is the stacktrace :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-12-31 14:12:25.347 ERROR 18056 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field pr in com.training.training.Service.ProduitServiceImpl required a bean of type 'com.training.training.Repos.ProduitRepository' that could not
be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.training.training.Repos.ProduitRepository' in your configuration.
Here are the features of my project :
- Spring Boot version 2.6.2
- Maven 3.8.3
- JDK 8
- MySQL database version 8.0
Here is my pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.training</groupId>
<artifactId>training</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>training</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
</properties>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here is my code for each class which constitutes my backend side :
TrainingApplication.java (main class) :
import com.training.training.Service.ProduitService;
import java.util.Date;
import com.training.training.Entities.Produit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TrainingApplication implements CommandLineRunner {
@Autowired
ProduitService produitService;
public static void main(String[] args) {
SpringApplication.run(TrainingApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
produitService.saveProduit(new Produit("PC Dell", 2600.0, new Date()));
produitService.saveProduit(new Produit("PC Asus", 2800.0, new Date()));
produitService.saveProduit(new Produit("Imprimante Epson", 900.0, new Date()));
}
}
ProduitController.java :
package com.training.training.Controller;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import com.training.training.Entities.Produit;
import com.training.training.Service.ProduitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ProduitController {
@Autowired
ProduitService ps;
@RequestMapping("/showCreate")
public String showCreate() {
return "createProduit";
}
@PostMapping("/saveProduit")
public String saveProduit(@ModelAttribute("Produit") Produit p, @RequestParam("dateCreationProduit") String date,
ModelMap modelMap) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dateCreation = sdf.parse(String.valueOf(date));
p.setDateCreation(dateCreation);
Produit savedProduit = ps.UpdateProduit(p);
String msg = "produit enregistré avec Id " + savedProduit.getIdProduit();
modelMap.addAttribute("msg", msg);
return "createProduit";
}
@RequestMapping("/ListeProduits")
public String listeProduits(ModelMap modelMap, @RequestParam(name = "page", defaultValue = "0") int page,
@RequestParam(name = "size", defaultValue = "2") int size) {
Page<Produit> listeProduits = ps.getAllProduitsParPage(page, size);
modelMap.addAttribute("produits", listeProduits);
modelMap.addAttribute("pages", new int[listeProduits.getTotalPages()]);
modelMap.addAttribute("currentPage", page);
return "listeProduits";
}
@DeleteMapping("/supprimerProduit")
public String supprimerProduit(@RequestParam("id") Long id, ModelMap modelMap) {
ps.deleteProduitById(id);
List<Produit> listeProduits = ps.getAllProduit();
modelMap.addAttribute("produits", listeProduits);
return "listeProduits";
}
@RequestMapping("/modifierProduit")
public String modifierProduit(@RequestParam("id") Long id, ModelMap modelMap) {
Produit p = ps.getProduit(id);
modelMap.addAttribute("produits", p);
return "editerProduit";
}
@PostMapping("/modifierupdateProduit")
public String updateProduit(@ModelAttribute("produit") Produit p, ModelMap modelMap, String date)
throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(String.valueOf(date));
p.setDateCreation(d);
ps.UpdateProduit(p);
List<Produit> listeProduits = ps.getAllProduit();
modelMap.addAttribute("produits", listeProduits);
return "listeProduits";
}
}
Produit.java (my unique entity) :
package com.training.training.Entities;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Produit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idProduit;
private String nomProduit;
private Double prixProduit;
private Date dateCreation;
public Produit() {
super();
}
public Produit(String nomProduit, Double prixProduit, Date dateCreation) {
super();
this.nomProduit = nomProduit;
this.prixProduit = prixProduit;
this.dateCreation = dateCreation;
}
public Long getIdProduit() {
return idProduit;
}
public void setIdProduit(Long idProduit) {
this.idProduit = idProduit;
}
public String getNomProduit() {
return nomProduit;
}
public void setNomProduit(String nomProduit) {
this.nomProduit = nomProduit;
}
public Double getPrixProduit() {
return prixProduit;
}
public void setPrixProduit(Double prixProduit) {
this.prixProduit = prixProduit;
}
public Date getDateCreation() {
return dateCreation;
}
public void setDateCreation(Date dateCreation) {
this.dateCreation = dateCreation;
}
@Override
public String toString() {
return "Produit [ idProduit = " + idProduit + ", nomProduit = " + nomProduit +
", prixProduit = " + prixProduit + ", dateCreation = " + dateCreation + "]";
}
}
ProduitRepository.java (repos for Produit entity) :
package com.training.training.Repos;
import com.training.training.Entities.Produit;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProduitRepository extends JpaRepository<Produit, Long> {
}
ProduitService.java
package com.training.training.Service;
import java.util.List;
import com.training.training.Entities.Produit;
import org.springframework.data.domain.Page;
public interface ProduitService {
public Produit saveProduit(Produit p);
public Produit UpdateProduit(Produit p);
void deleteProduit(Produit p);
void deleteProduitById(Long id);
Produit getProduit(Long id);
List<Produit> getAllProduit();
public Page<Produit> getAllProduitsParPage(int page, int size);
}
ProduitServiceImpl.java (the implementation of previous class ProduitService.java) :
package com.training.training.Service;
import java.util.List;
import com.training.training.Entities.Produit;
import com.training.training.Repos.ProduitRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
@Service
public class ProduitServiceImpl implements ProduitService {
@Autowired
ProduitRepository pr;
@Override
public Produit saveProduit(Produit p) {
pr.save(p);
return p;
}
@Override
public Produit UpdateProduit(Produit p) {
pr.save(p);
return p;
}
@Override
public void deleteProduit(Produit p) {
pr.delete(p);
}
@Override
public void deleteProduitById(Long id) {
pr.deleteById(id);
}
@Override
public Produit getProduit(Long id) {
Produit p = pr.findById(id).get();
return p;
}
@Override
public List<Produit> getAllProduit() {
List<Produit> l = pr.findAll();
return l;
}
public Page<Produit> getAllProduitsParPage(int page, int size) {
return pr.findAll(PageRequest.of(page, size));
}
}
Here are the templates which constitute my frontend side:
createProduit.html (the view for creating Product and store them into DB) :
<!DOCTYPE html>
<html>
<html xmlns:th="http://www.thymeleaf.org">
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/4.3.1/css/bootstrap.min.css"/>
<head>
<meta charset="utf-8">
<title>Ajouter Produit</title>
</head>
<body>
<div class="container mt-5">
<div class="card-body">
<form action="saveProduit" method="post">
<div class="form-group">
<label class="control-label">Nom Produit :</label>
<input type="text" name="nomProduit" class="form-control" />
</div>
<div class="form-group">
<label class="control-label">Prix Produit :</label>
<input type="text" name="prixProduit" class="form-control" />
</div>
<div class="form-group">
<label class="control-label">date création :</label>
<input type="date" name="dateCreationProduit" class="form-control" />
</div>
<div>
<button type="submit" class="btn btn-primary">Ajouter</button>
</div>
</form>
</div>
<p th:text="${msg}"></p>
<br />
<br />
<a href="ListeProduits">Liste Produits</a>
</div>
</body>
</html>
listerProduit.java (the view which show a list of all product stored into DB) :
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/4.3.1/css/bootstrap.min.css" />
<head>
<meta charset="utf-8">
<title>Liste des Produits</title>
</head>
<body>
<div class="container mt-5">
<div class="card">
<div class="card-header">
Liste des Produits
</div>
<div class="card-body">
<table class="table table-striped">
<tr>
<th>ID</th>
<th>Nom Produit</th>
<th>Prix</th>
</tr>
<tr th:each="p:${produits.content}">
<td th:text="${p.idProduit}"></td>
<td th:text="${p.nomProduit}"></td>
<td th:text="${p.prixProduit}"></td>
</tr>
</table>
</div>
</div>
</div>
</body>
</html>
editerProduit.html (the view for updating a product initially stored into DB) :
<!DOCTYPE html>
<html>
<html xmlns:th="http://www.thymeleaf.org">
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/4.3.1/css/bootstrap.min.css"/>
<head>
<meta charset="utf-8">
<title>Modifier un Produit</title>
</head>
<body>
<div class="container mt-5">
<div class="card-body">
<form action="updateProduit" method="post">
<div class="form-group">
<label class="control-label">ID Produit :</label>
<input type="text" name="idProduit" th:value="${produit.idProduit}" readonly class="form-control" />
</div>
<div class="form-group">
<label class="control-label">Nom Produit :</label>
<input type="text" name="nomProduit" th:value="${produit.nomProduit}" class="form-control" />
</div>
<div class="form-group">
<label class="control-label">Prix Produit :</label>
<input type="text" name="prixProduit" th:value="${produit.prixProduit}" class="form-control" />
</div>
<div class="form-group">
<label class="control-label"> Date création :</label>
<fmt:formatDate pattern="yyyy-MM-dd" th:value="${produit.dateCreation}" var="formatDate"/>
<input type="date" name="date" th:value="${formatDate}" class="form-control" />
</div>
<div>
<button type="submit" class="btn btn-primary">Modifier</button>
</div>
</form>
</div>
<br />
<br />
<a href="ListeProduits">Liste Produits</a>
</div>
</body>
</html>
Here my file architecture :
Any help would be much appreciated.
Best regards,
YT