Depuis la console de réaction, j'obtiens l'erreur "Impossible de charger la ressource : le serveur a répondu avec le statut 500 ()" pointant vers l'url ":8080/api/review-add"
Depuis le backend Spring Boot, j'obtiens le message d'erreur "La propriété non nulle fait référence à une valeur nulle ou transitoire : com.reactspringboot.bookclubbackend.entity.Review.account"
Le problème est que lorsque je fais une requête POST dans Postman, je n'obtiens pas d'erreur et l'objet est publié dans la base de données.
Voici le fichier du backend Spring Boot :
forum.java
@Entity @Table(name="Forum") public class Forum { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private long id; @Column(name="book_name") private String bookName; @Column(name="book_image") private String bookImage; @Lob @Column(name="description") private String description; @OneToMany(mappedBy = "forum", cascade = CascadeType.ALL) private List<Review> reviews; public Forum() { } public Forum(String bookName, String bookImage, String description, List<Review> reviews) { this.bookName = bookName; this.bookImage = bookImage; this.description = description; this.reviews = reviews; } public long getId() { return id; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getBookImage() { return bookImage; } public void setBookImage(String bookImage) { this.bookImage = bookImage; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } // using 'JsonProperty' to prevent infinite recursion @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public List<Review> getReviews() { return reviews; } public void setReviews(List<Review> reviews) { this.reviews = reviews; } }
compte.java
@Entity @Table(name="account") public class Account { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private long id; @Column(name="account_name") private String accountName; @Column(name="password") private String password; @Column(name="email") private String email; @Column(name="profile_image") private String profileImage; @Column(name="role") private String role; @Column(name="date_joined") @CreationTimestamp private Date dateJoined; @OneToMany(mappedBy = "account", cascade = CascadeType.ALL) private List<Review> reviews; public Account() { } public Account(String accountName, String password, String email, String profileImage, String role, Date dateJoined, List<Review> reviews) { this.accountName = accountName; this.password = password; this.email = email; this.profileImage = profileImage; this.role = role; this.dateJoined = dateJoined; this.reviews = reviews; } public long getId() { return id; } public String getAccountName() { return accountName; } public void setAccountName(String accountName) { this.accountName = accountName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getProfileImage() { return profileImage; } public void setProfileImage(String profileImage) { this.profileImage = profileImage; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public Date getDateJoined() { return dateJoined; } public void setDateJoined(Date dateJoined) { this.dateJoined = dateJoined; } // using 'JsonProperty' to prevent infinite recursion @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public List<Review> getReviews() { return reviews; } public void setReviews(List<Review> reviews) { this.reviews = reviews; } }
Review.java
@Entity @Table(name="review") public class Review { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private long id; @Column(name="date_posted") @CreationTimestamp private Date datePosted; @Lob @Column(name="comment") private String comment; @Column(name="star_rating") private double starRating; //@JsonIgnore @ManyToOne @JoinColumn(name = "account_id",nullable = false, insertable = true, updatable = true) private Account account; //@JsonIgnore @ManyToOne @JoinColumn(name = "forum_id",nullable = false, insertable = true, updatable = true) private Forum forum; public Review() { } public Review(Date datePosted, String comment, double starRating, Account account, Forum forum) { this.datePosted = datePosted; this.comment = comment; this.starRating = starRating; this.account = account; this.forum = forum; } public long getId() { return id; } public Date getDatePosted() { return datePosted; } public void setDatePosted(Date datePosted) { this.datePosted = datePosted; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public double getStarRating() { return starRating; } public void setStarRating(double starRating) { this.starRating = starRating; } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } public Forum getForum() { return forum; } public void setForum(Forum forum) { this.forum = forum; } }
ReviewRepository.java
@CrossOrigin(origins = "http://localhost:3000") public interface ReviewRepository extends JpaRepository<Review, Long> { @Query(value = "SELECT * FROM Review r where r.forum_id = :forum_id", nativeQuery = true) public List<Review> getReviewsUsingForumId(@Param("forum_id") Long forum_id); }
ReviewController.java
@CrossOrigin(origins = "http://localhost:3000") @RestController @RequestMapping("/api/") public class ReviewController { @Autowired private ReviewRepository reviewRepository; // create review rest api //@CrossOrigin(origins = "http://localhost:3000") @PostMapping("/review-add") public Review createReview(@RequestBody Review review) { return reviewRepository.save(review); } @GetMapping("/forum-reviews/{forumId}") public List<Review> getReviewsByForumId(@RequestBody @PathVariable Long forumId) { return reviewRepository.getReviewsUsingForumId(forumId); } }
Depuis l'interface React
PostComponent.js
function PostComponent() { // right now only using static data for testing const [review, setReview] = useState({datePosted: "2023-07-26", comment: "", starRating: 5.0, account: { id: 1 }, forum: { id: 1 }}); const postURL = "http://localhost:8080/api/review-add"; function changeHandler (event) { setReview({comment: event.target.value}); } function submit(event) { event.preventDefault(); axios.post(postURL, review) } useEffect(() => { console.log(review.comment) }, [review]); return ( <div> <div className="container"> <h2>Post Review</h2> <form onSubmit={(event) => submit(event)}> <div className="form-group"> <label>Comment</label> <input placeholder="Commet here" name="comment" className="form=control" value={review.comment} onChange={changeHandler}/> </div> <button>Submit</button> </form> </div> </div> ) } export default PostComponent;
Dans le corps du facteur, je sélectionne raw et je définis sur JSON et lorsque j'utilise cette requête POST pour l'entité "review", cela fonctionne :
{ "datePosted": "2023-07-26", "comment": "From postman.", "starRating": 5.0, "account": { "id": 1 }, "forum": { "id": 1 } }
Le forum avec l'identifiant 1 et le compte avec l'identifiant 1 existent dans la base de données.
Si quelqu'un peut m'aider ou m'indiquer une solution à ce problème, je lui en serais très reconnaissant. Je suis coincé avec ce problème depuis des jours et je suis à court d'idées.
Si le serveur s'attend à recevoir l'intégralité de la charge utile :
Le serveur ne le recevra pas après avoir effectué les opérations suivantes :
Le serveur recevra uniquement :
Lorsque vous souhaitez mettre à jour une seule propriété dans l'état, la mise à jour doit quand même inclure le reste de l'objet pour préserver l'intégralité de l'objet :
ou :
Au fait... les outils de débogage de votre navigateur peuvent vous aider à cibler précisément ce problème. Vous pouvez observer la charge utile dans la requête AJAX envoyée, voir que ce n'est pas ce à quoi vous vous attendez, et exclure immédiatement toutle code côté serveur comme cause du problème et commencer à vous concentrer sur le débogage côté client.