http://localhost:8080/basket/delete/%7BbasketId%7D?basketId=7&bookTitle=Ritle2&author=Rauther2&publisher=Publisher&quantity=1&price=5.0
The above URL is what is searched for upon clicking on a 'Delete item from basket' button in my Spring app. The controller is supposed to take in this Basket Id (in this case = 7) and delete it from the basket. However I am getting the below error as it seems to be reading in "{basketId}" rather than the Id itself:
[org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "{basketId}"]
Why is this happening and how do I ensure it takes in the value of the basketId instead?
<tr th:each="basketItem : ${basket}">
<form action="/basket/delete/{basketId}" method="delete">
<td> <input name="basketId" th:value="${basketItem.basketId}" readonly> </td>
<td> <input name="bookTitle" th:value="${basketItem.bookTitle}" readonly> </td>
<td> <input name="author" th:value="${basketItem.author}" readonly> </td>
<td> <input name="publisher" th:value="${basketItem.publisher}"readonly> </td>
<td> <input name="quantity" th:value="${basketItem.quantity}" readonly> </td>
<td> <input name="price" th:value="${basketItem.price}" readonly> </td>
<td> <button > Delete from basket</button></td>
</form>
</tr>
@DeleteMapping("/basket/delete/{basketId}")
String deleteBook(@PathVariable Long basketId, Model model) {
System.out.println("Delte mapping : " + basketId);
if (basketRepository.existsById(basketId)){
basketRepository.deleteById(basketId);
}
else {
System.out.println("Item does not exist!");
};
//basketRepository.save(basket);
model.addAttribute("basket", basketRepository.findAll());
return "basket/list";
}
@GetMapping("/basket/delete/{basketId}")
public String deleteItem(@PathVariable Long basketId,Model model) {
System.out.println("Get mapping : " + basketId);
Basket basketItem = basketRepository.findById(basketId)
.orElseThrow();
basketRepository.delete(basketItem);
model.addAttribute("basket", basketRepository.findAll());
return "basket/list";
}
package springLibrary.domain;
import javax.persistence.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@Entity
public class Basket {
private @Id
@GeneratedValue
Long basketId;
private String bookTitle;
private String author;
private String publisher;
private int quantity;
private double price;
public Basket() {
}
public Basket(String bookTitle, String author, String publisher, int quantity, double price) {
this.bookTitle = bookTitle;
this.author = author;
this.publisher = publisher;
this.quantity = quantity;
this.price = price;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Basket basket = (Basket) o;
return Objects.equals(bookTitle, basket.bookTitle);
}
@Override
public int hashCode() {
return Objects.hash(bookTitle);
}
@Override
public String toString() {
return "Basket{" +
"basketId=" + basketId +
", bookTitle='" + bookTitle + '\'' +
", author='" + author + '\'' +
", publisher='" + publisher + '\'' +
", quantity=" + quantity +
", price=" + price +
'}';
}
public Long getBasketId() {
return basketId;
}
public void setBasketId(Long basketId) {
this.basketId = basketId;
}
public String getBookTitle() {
return bookTitle;
}
public void setBookTitle(String bookTitle) {
this.bookTitle = bookTitle;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
Thank you to @M. Deinum for this - the reason it was being read as a String was due to the formatting of the action itself.
In Thymeleaf, it should be structured as so:
<form th:action="@{/basket/delete/{basketId}(basketId=${basketItem.basketId})}" method="delete">