I am trying to create a schema where I have 3 tables, Customer, Orders, and Products that have One to Many relationships. For example, 1 Customer can have many Orders and 1 Order can have many Products (is this possible?). I am able to add a Customer that contains a list of Orders through my post request in postman to satisfy the relationship. However, I cannot do the same for adding a list of Products to an Order. I am getting the error in OrderResource java.lang.IllegalArgumentException: Entity must not be null.
. Why is my OrderResource reading a null entity when trying to post a new Order with a list of Products? How can I fix this? Thanks for any help in advance.
HTTP Get request from CustomerResource that shows an empty "products" list in "orders"
{
"id": 1,
"firstName": "Charlie",
"lastName": "Madge",
"email": "cmadge0@fc2.com",
"address": "21556 Arizona Crossing",
"password": "l7QFUwG",
"orders": [
{
"id": 1,
"tracking": "123456789",
"date": "2012-04-23T18:25:43.000+00:00",
"total": "100",
"quantity": "4",
"payment": "Paypal",
"products": []
},
{
"id": 2,
"tracking": "987654321",
"date": "2022-04-23T18:25:43.000+00:00",
"total": "90",
"quantity": "3",
"payment": "Visa",
"products": []
}
]
}
HTTP Post request I used for /assignProducts endpoint which produced the internal server error status 500
{
"orders": {
"id": "1",
"tracking": "123456789",
"date": "2012-04-23T18:25:43.511Z",
"total": "100",
"quantity": "4",
"payment": "Paypal",
"products": [
{
"title": "abc",
"price": "10",
"image": "fdfhsdfh"
}
]
}
}
Orders.java
@Entity
public class Orders implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, updatable = false)
private Long id;
private String tracking;
private Date date;
private String total;
private String quantity;
private String payment;
@JsonIgnore
@OneToMany(targetEntity = Products.class, cascade = CascadeType.ALL)
@JoinColumn(name = "op_fk", referencedColumnName = "id")
private List<Products> products;
public Orders() { }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getTracking() { return tracking; }
public void setTracking(String tracking) { this.tracking = tracking; }
public Date getDate() { return date; }
public void setDate(Date date) { this.date = date; }
public String getTotal() { return total; }
public void setTotal(String total) { this.total = total; }
public String getQuantity() { return quantity; }
public void setQuantity(String quantity) { this.quantity = quantity; }
public String getPayment() { return payment; }
public void setPayment(String payment) { this.payment = payment; }
public List<Products> getProducts() { return products; }
public void setProducts(List<Products> products) { this.products = products; }
}
Products.java
@Entity
public class Products implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, updatable = false)
private Long id;
private String title;
private String price;
private String image;
public Products() { }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getPrice() { return price; }
public void setPrice(String price) { this.price = price; }
public String getImage() { return image; }
public void setImage(String image) { this.image = image; }
}
OrdersResource.java
@RestController
@RequestMapping("/orders")
public class OrdersResource {
@Autowired
private final OrdersService ordersService;
public OrdersResource(OrdersService ordersService) { this.ordersService = ordersService; }
@GetMapping("/all")
public ResponseEntity<List<Orders>> getAllOrders(){
List<Orders> orders = ordersService.findAllOrders();
return new ResponseEntity<>(orders, HttpStatus.OK);
}
@GetMapping("/find/{id}")
public ResponseEntity<Orders> getOrderById(@PathVariable("id") Long id){
Orders orders = ordersService.findOrderById(id);
return new ResponseEntity<>(orders, HttpStatus.OK);
}
@PostMapping("/add")
public ResponseEntity<Orders> addOrder(@RequestBody Orders order){
Orders newOrder = ordersService.addOrder(order);
return new ResponseEntity<>(newOrder, HttpStatus.CREATED);
}
@PostMapping("/assignProducts")
public ResponseEntity<Orders> assignProduct(@RequestBody AssignProductRequest request){
Orders newOrder = ordersService.addOrder(request.getOrder());
return new ResponseEntity<>(newOrder, HttpStatus.CREATED);
}
@PostMapping("/update")
public ResponseEntity<Orders> updateOrder(@RequestBody AssignProductRequest request){
Orders updateOrder = ordersService.updateOrder(request.getOrder());
return new ResponseEntity<>(updateOrder, HttpStatus.OK);
}
@Transactional
@DeleteMapping("/delete/{id}")
public ResponseEntity<?> deleteOrder(@PathVariable("id") Long id){
ordersService.deleteOrderById(id);
return new ResponseEntity<>(HttpStatus.OK);
}
}
OrdersService.java
@Service
public class OrdersService {
private final OrdersRepo ordersRepo;
@Autowired
public OrdersService(OrdersRepo ordersRepo) { this.ordersRepo = ordersRepo; }
public Orders addOrder(Orders order){ return ordersRepo.save(order); }
public List<Orders> findAllOrders(){ return ordersRepo.findAll(); }
public Orders updateOrder(Orders order){ return ordersRepo.save(order); }
public Orders findOrderById(Long id){
return ordersRepo.findOrderById(id)
.orElseThrow(()-> new OrderNotFoundException("Order by id " + id + " was not found"));
}
public void deleteOrderById(Long id){ ordersRepo.deleteOrderById(id); }
}
AssignProductsRequest.java
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class AssignProductRequest { private Orders order; }
ProductsResource.java
@RestController
@RequestMapping("/products")
public class ProductsResource {
@Autowired
private final ProductsService productsService;
public ProductsResource(ProductsService productsService) { this.productsService = productsService; }
@GetMapping("/all")
public ResponseEntity<List<Products>> getAllProducts(){
List<Products> products = productsService.findAllProducts();
return new ResponseEntity<>(products, HttpStatus.OK);
}
@GetMapping("/find/{id}")
public ResponseEntity<Products> getProductById(@PathVariable("id") Long id){
Products product = productsService.findProductById(id);
return new ResponseEntity<>(product, HttpStatus.OK);
}
@PostMapping("/add")
public ResponseEntity<Products> addProduct(@RequestBody Products product){
Products newProduct = productsService.addProduct(product);
return new ResponseEntity<>(newProduct, HttpStatus.CREATED);
}
@PostMapping("/update")
public ResponseEntity<Products> updateProduct(@RequestBody ProductsRequest request){
Products updateProduct = productsService.updateProduct(request.getProduct());
return new ResponseEntity<>(updateProduct, HttpStatus.OK);
}
@Transactional
@DeleteMapping("delete/{id}")
public ResponseEntity<?> deleteProduct(@PathVariable("id") Long id){
productsService.deleteProduct(id);
return new ResponseEntity<>(HttpStatus.OK);
}
}
ProductsService.java
@Service
public class ProductsService {
private final ProductsRepo productsRepo;
@Autowired
public ProductsService(ProductsRepo productsRepo) { this.productsRepo = productsRepo; }
public Products addProduct(Products product){ return productsRepo.save(product); }
public Products updateProduct(Products products){ return productsRepo.save(products); }
public List<Products> findAllProducts(){ return productsRepo.findAll(); }
public Products findProductById(Long id){
return productsRepo.findProductById(id)
.orElseThrow(()-> new ProductNotFoundException("Product by id " + id + " was not found"));
}
public void deleteProduct(Long id){
productsRepo.deleteProductById(id);
}
}
OrdersRepo.java
public interface OrdersRepo extends JpaRepository<Orders, Long> {
void deleteOrderById(Long id);
Optional<Orders> findOrderById(Long id);
}
ProductsRepo.java
public interface ProductsRepo extends JpaRepository<Products, Long> {
void deleteProductById(Long id);
Optional<Products> findProductById(Long id);
}