I am trying to extend my implementation by adding a second repository (Review). However, when I try to access http://localhost:8080/api/reviews I get the above error. Can anyone spot where I’ve messed up? I’m really knew to this so no doubt I’ve made a rookie mistake.
Folder structure
ProductController:
package gerry.stockcontrol.controller;
import gerry.stockcontrol.exception.ProductNotFoundException;
import gerry.stockcontrol.model.Product;
import gerry.stockcontrol.service.ProductServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
@RequestMapping("/api/products")
//http://localhost:8080/api/products
public class ProductController {
public ProductController(ProductServiceImpl productServiceImpl) {
this.productServiceImpl = productServiceImpl;
}
@Autowired
private final ProductServiceImpl productServiceImpl;
@GetMapping("/searchname")
public List<Product> searchProductsByName(@RequestParam(value="name") String name){
return productServiceImpl.findByName(name);
}
@GetMapping("/searchdescription")
public List<Product> searchProductsByDescription(@RequestParam(value="description") String description){
return productServiceImpl.findByDescription(description);
}
@GetMapping
public List<Product> getAllProducts(){
return productServiceImpl.getAllProducts();
}
@GetMapping("/{id}")
public Product getProductById(@PathVariable Long id) throws ProductNotFoundException {
return productServiceImpl.getProductById(id);
}
@GetMapping("/searchstocklevel")
public List<Product> searchProductsByStockLevel(@RequestParam(value="stocklevel") int stocklevel){
return productServiceImpl.findByStockLevel(stocklevel);
}
@PostMapping
public Product createProduct(@RequestBody Product product){
return productServiceImpl.createProduct(product);
}
@PutMapping("/{id}")
public Product updateProduct(@PathVariable Long id, @RequestBody Product product) throws ProductNotFoundException{
return productServiceImpl.updateProduct(id, product);
}
@DeleteMapping("{id}")
public void deleteProduct(@PathVariable Long id) throws ProductNotFoundException
{
productServiceImpl.deleteProduct(id);
}
}
ReviewController:
package gerry.stockcontrol.controller;
import gerry.stockcontrol.exception.ReviewNotFoundException;
import gerry.stockcontrol.model.Review;
import gerry.stockcontrol.service.ReviewServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
@RequestMapping("/api/reviews")
//http://localhost:8080/api/reviews
public class ReviewController {
public ReviewController(ReviewServiceImpl reviewServiceImpl) {
this.reviewServiceImpl = reviewServiceImpl;
}
@Autowired
private final ReviewServiceImpl reviewServiceImpl;
@GetMapping
public List<Review> getAllReviews(){
return reviewServiceImpl.getAllReviews();
}
@GetMapping("/{id}")
public Review getReviewById(@PathVariable Long id) throws ReviewNotFoundException {
return reviewServiceImpl.getReviewById(id);
}
}
Product Model:
package gerry.stockcontrol.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String description;
@Column(nullable = false)
private Double price;
@Column(nullable = false)
private Integer stock;
@OneToMany(mappedBy = "product")
@JsonIgnore
private List<Review> reviews;
//Getters and Setters
public Long getID(){
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name){
this.name = name;
}
public String getDescription(){
return description;
}
public void setDescription(String description){
this.description = description;
}
public Double getPrice(){
return price;
}
public void setPrice(Double price){
this.price = price;
}
public Integer getStock(){
return stock;
}
public void setStock(Integer stock){
this.stock = stock;
}
@Override
public String toString()
{
return "Product{" +
"id=" + id +
", name='" + name + ''' +
", description='" + description + ''' +
", price='" + price + ''' +
", stock='" + stock + ''' +
", reviews='" + reviews + ''' +
'}';
}
}
Review Model:
package gerry.stockcontrol.model;
import javax.persistence.*;
@Entity
@Table(name = "reviews")
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private Integer rating;
@Column(nullable = false)
private String comment;
@ManyToOne
private Product product;
public Review(Product product, int rating, String comment) {
this.rating = rating;
this.comment = comment;
this.product = product;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
@Override
public String toString()
{
return "Review{" +
"id=" + id +
", rating='" + rating + ''' +
", comment='" + comment + ''' +
'}';
}
}
ProductRepository:
package gerry.stockcontrol.repository;
import gerry.stockcontrol.model.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product>findByNameContainingIgnoreCase(String name);
List<Product>findByDescriptionContainingIgnoreCase(String description);
List<Product>findByStockGreaterThanEqual(int stockLevel);
}
ReviewRepository:
package gerry.stockcontrol.repository;
import gerry.stockcontrol.model.Review;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface ReviewRepository extends JpaRepository<Review, Long> {
List<Review>findByProductId(Long productId);
}
ProductServiceImpl:
package gerry.stockcontrol.service;
import gerry.stockcontrol.exception.ProductNotFoundException;
import gerry.stockcontrol.model.Product;
import gerry.stockcontrol.repository.ProductRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductServiceImpl {
private final ProductRepository productRepository;
public ProductServiceImpl(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public List<Product> getAllProducts() {
return productRepository.findAll();
}
public Product getProductById(Long id) throws ProductNotFoundException{
return productRepository.findById(id)
.orElseThrow(() -> new ProductNotFoundException("Product not found with id: " + id));
}
public Product createProduct(Product product){
return productRepository.save(product);
}
public Product updateProduct(Long id, Product product) throws ProductNotFoundException{
Product existingProduct = getProductById(id);
existingProduct.setName(product.getName());
existingProduct.setDescription(product.getDescription());
existingProduct.setPrice(product.getPrice());
existingProduct.setStock(product.getStock());
return productRepository.save(existingProduct);
}
public void deleteProduct(Long id) throws ProductNotFoundException{
getProductById(id);
productRepository.deleteById(id);
}
public List<Product> findByName(String name){
return productRepository.findByNameContainingIgnoreCase(name);
}
public List<Product> findByDescription(String description){
return productRepository.findByDescriptionContainingIgnoreCase(description);
}
public List<Product> findByStockLevel(int stockLevel){
return productRepository.findByStockGreaterThanEqual(stockLevel);
}
}
ReviewServiceImpl:
package gerry.stockcontrol.service;
import gerry.stockcontrol.exception.ProductNotFoundException;
import gerry.stockcontrol.exception.ReviewNotFoundException;
import gerry.stockcontrol.model.Product;
import gerry.stockcontrol.model.Review;
import gerry.stockcontrol.repository.ReviewRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ReviewServiceImpl {
private final ReviewRepository reviewRepository;
public ReviewServiceImpl(ReviewRepository reviewRepository) {
this.reviewRepository = reviewRepository;
}
public List<Review> getAllReviews() {
return reviewRepository.findAll();
}
public Review getReviewById(Long id) throws ReviewNotFoundException {
return reviewRepository.findById(id)
.orElseThrow(() -> new ReviewNotFoundException("Product not found with id: " + id));
}
public List<Review> getReviewsByProductId(Long productId) {
return reviewRepository.findByProductId(productId);
}
}
StockControlApplication:
package gerry.stockcontrol;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StockControlApplication {
public static void main(String[] args)
{
SpringApplication.run(StockControlApplication.class, args);
}
}
I’ve made sure the folder structure is correct re. main. I’ve pretty much just did for Review exactly as I did for Product so was expecting to be able to call http://localhost:8080/api/reviews and get back all Reviews like I did for Products.
Tony McConville is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.